import { injectable } from 'inversify'; import { IBusMode } from '../../common/bus'; import { OperationLevel } from '../../common/signature'; import { InstanceFactory } from '../../common/instanceFactory'; import { IDisposable, Mapping, nextId } from 'ts-toolset'; import { isNumber, isUndefined } from 'ts-toolset/dist/common/types'; /** 事件配置 */ export interface EventOptions { /** 事件Id */ id: string; /** 事件只执行一次 */ once: boolean; /** 事件级别 */ level: OperationLevel; /** 时间间隔(毫秒) */ interval?: number; /** 作用域 */ scope?: any; } /** 注册监听事件配置 */ export type RegisterEventOptions = Partial & { /** 是否覆盖原本的监听事件,若覆盖的事件含有 level==framework 的监听事件,则只覆盖自定义的监听 */ cover: boolean, /** 覆盖指定的事件 */ eventId: string }>; /** 事件体 */ interface IEvent extends IDisposable { readonly id: string; readonly once: boolean; readonly level: OperationLevel; /** 调用绑定的事件函数 */ invoke(...params: any[]): void; /** 异步调用绑定的事件函数 */ invokeAsync(...params: any[]): Promise; /** 重设事件 */ reset(callback: Function, options?: Partial): void; } /** 事件体 */ class Event implements IEvent { private _options: EventOptions; /** 事件执行的逻辑 */ private _callback: Function; /** 上次事件调用的时间,用于防抖判断 */ private _previousInvokeTime: number = 0; constructor(callback: Function, options: EventOptions) { this._options = options; this._callback = callback; } /** 事件Id */ get id() { return this._options.id; } /** 是否只执行一次 */ get once() { return this._options.once; } /** 事件级别 */ get level() { return this._options.level; } private _debounce() { if (isNumber(this._options.interval)) { if (Date.now() - this._previousInvokeTime < this._options.interval) { return false; } this._previousInvokeTime = Date.now(); } return true; } invoke(params: any[]) { // 处理方法调用的作用域 this._debounce() && this._callback.apply(this._options.scope ?? this, params); } invokeAsync(params: any[]) { return new Promise((resolve, reject) => { this._debounce() ? this._callback.apply(this._options.scope ?? this, [resolve, reject, ...params]) : reject(); }); } reset(callback: Function, options?: Partial) { this._callback = callback; if (options) { this._options = { ...this._options, ...options }; } } dispose() { } } /** 事件总线 */ export interface IEventBus extends IBusMode { /** 注册监听事件 */ register(eventName: string, callback: Function, options: RegisterEventOptions): IEventBus; /** 取消指定事件监听的回调,指定Id时只删除相应回调 * @description 若监听事件绑定系统事件(level==framework),该监听事件将保留系统事件,移除用户绑定事件 */ unregister(eventName: string, eventId?: string): IEventBus; /** 获取事件 */ get(eventName: string): IEvent[] | undefined; /** 触发事件 */ emit(eventName: string, ...params: any[]): IEventBus; /** 触发异步事件 */ emitAsync(eventName: string, ...params: any[]): void; /** 是否有指定监听事件 */ hasEvent(eventName: string, eventId?: string): boolean; /** 获取一个可用的事件实例 */ getEventInstance(callback: Function, options?: Partial): IEvent; } /** 事件总线 */ @injectable() export class EventBus implements IEventBus { /** 事件工厂 */ private _factory: InstanceFactory = new InstanceFactory(); /** 事件总线存储 */ private _eventStore: Map = new Map(); /** 移除监听事件 */ private _removeEvent(eventName: string, eventId?: string) { let events = this._eventStore.get(eventName) as Event[]; if (!isUndefined(events)) { if (isUndefined(eventId)) { events = events.filter(e => e.level === OperationLevel.framework); events.length > 0 ? this._eventStore.set(eventName, events) : this._eventStore.delete(eventName); } else { const index = events.findIndex(event => eventId === event.id && event.level === OperationLevel.user); index > -1 && events.splice(index, 1); } } } /** 注册监听事件 */ register(eventName: string, callback: Function, { cover, eventId, ...options }: RegisterEventOptions = {}): EventBus { let event = this.getEventInstance(callback, options); if (this._eventStore.has(eventName)) { if (cover) { this._removeEvent(eventName, eventId); const events = this._eventStore.get(eventName); events ? events.push(event) : this._eventStore.set(eventName, [event]); } else { (this._eventStore.get(eventName) as Event[]).push(event); } } else { this._eventStore.set(eventName, [event]); } return this; } /** 取消指定事件监听的回调,指定Id时只删除相应回调 * @description 若监听事件绑定系统事件(level==framework),该监听事件将保留系统事件,移除用户绑定事件 */ unregister(eventName: string, eventId?: string): EventBus { this._removeEvent(eventName, eventId); return this; } get(eventName: string): Event[] | undefined { return this._eventStore.get(eventName); } emit(eventName: string, ...params: any[]): EventBus { const events = this._eventStore.get(eventName); if (events) { events.forEach(event => event.invoke(params)); // 移除只响应用一次的事件 if (events.some(event => event.once)) { this._eventStore.set(eventName, events.filter(event => event.once)); } } return this; } async emitAsync(eventName: string, ...params: any[]) { const events = this._eventStore.get(eventName); if (!isUndefined(events)) { await Promise.all(events.map(e => e.invokeAsync(params))); } } hasEvent(eventName: string, eventId?: string): boolean { if (this._eventStore.has(eventName)) { return eventId === undefined ? true : !!this._eventStore.get(eventName)?.find(event => event.id === eventId); } return false; } getEventInstance(callback: Function, options?: Partial): Event { // 预设事件配置 let presetOptions: EventOptions = { id: nextId(), once: false, level: OperationLevel.user }; options && (presetOptions = { ...presetOptions, ...options }); // 获取事件实例 let [event, isNew] = this._factory.getInstanceAndSign(Event, callback, presetOptions); // 重置从缓存中获取的实例 !isNew && event.reset(callback, presetOptions); return event; } dispose() { // 清除所有事件的引用 this._factory.recycle(); this._eventStore.forEach(events => events.splice(0, events.length)); this._eventStore.clear(); } }