import type { IEventBuilder, IEventMap } from '../IEventBuilder.ts' interface HandlerWrapper any> { fn: T once: boolean } export class EventBuilderImpl implements IEventBuilder { private _eventHandlers = new Map>>() /** * 添加事件监听器 * @param eventName 事件名称 * @param handler 监听器 * @param options { immediate: 立即执行一次 immediateArgs: 立即执行的参数 once: 只监听一次 } * @returns 返回一个 `unsubscribe` 函数,用于移除当前监听 * @example * eventBus.subscribe('noArgs', () => {}) * eventBus.subscribe('greet', name => {}, { immediate: true, immediateArgs: ['abc'] }) * eventBus.subscribe('onResize', (w, h) => {}, { immediate: true, immediateArgs: [1, 2] }) */ subscribe( eventName: E, handler: F, options?: { immediate?: boolean immediateArgs?: Parameters once?: boolean }, ): () => void { if (!handler) return () => {} if (!this._eventHandlers.has(eventName)) { this._eventHandlers.set(eventName, new Set>()) } const set = this._eventHandlers.get(eventName)! const wrapper: HandlerWrapper = { fn: handler, once: options?.once ?? false } if (![...set].some((wrapper) => wrapper.fn === handler)) { set.add(wrapper) } if (options?.immediate) { try { handler(...(options.immediateArgs ?? [])) } catch (e) { console.error(e) } } return () => { set.delete(wrapper) // 如果该事件下无监听器,则删除集合 if (set.size === 0) this._eventHandlers.delete(eventName) } } /** * 移除事件监听器 * @param eventName 事件名称 * @param handler 监听器 * @example * eventBus.remove('noArgs', () => {}) */ remove(eventName: E, handler: F) { const set = this._eventHandlers.get(eventName) if (!set) return for (const wrapper of set) { if (wrapper.fn === handler) { set.delete(wrapper) } } if (set.size === 0) { this._eventHandlers.delete(eventName) } } /** * 通知事件 * @param eventName 事件名称 * @param args 参数 * @example * eventBus.notify('noArgs') * eventBus.notify('greet', 'Alice') * eventBus.notify('onResize', 1, 2) */ notify(eventName: E, ...args: Parameters) { if (!this._eventHandlers.has(eventName)) return const set = this._eventHandlers.get(eventName)! for (const wrapper of set) { try { wrapper.fn(...args) } catch (e) { console.error(e) } if (wrapper.once) { set.delete(wrapper) } } } destroy() { this._eventHandlers.clear() } }