Files
vue-desktop/src/events/impl/EventBuilderImpl.ts

108 lines
2.9 KiB
TypeScript
Raw Normal View History

2025-09-28 12:05:59 +08:00
import type { IEventBuilder, IEventMap } from '../IEventBuilder.ts'
2025-09-24 11:30:06 +08:00
interface HandlerWrapper<T extends (...args: any[]) => any> {
fn: T
once: boolean
}
export class EventBuilderImpl<Events extends IEventMap> implements IEventBuilder<Events> {
private _eventHandlers = new Map<keyof Events, Set<HandlerWrapper<Events[keyof Events]>>>()
/**
*
* @param eventName
* @param handler
* @param options { immediate: 立即执行一次 immediateArgs: 立即执行的参数 once: 只监听一次 }
2025-10-23 12:14:03 +08:00
* @returns `unsubscribe`
2025-09-24 11:30:06 +08:00
* @example
2025-10-23 12:14:03 +08:00
* eventBus.subscribe('noArgs', () => {})
* eventBus.subscribe('greet', name => {}, { immediate: true, immediateArgs: ['abc'] })
* eventBus.subscribe('onResize', (w, h) => {}, { immediate: true, immediateArgs: [1, 2] })
2025-09-24 11:30:06 +08:00
*/
2025-10-23 12:14:03 +08:00
subscribe<E extends keyof Events, F extends Events[E]>(
2025-09-24 11:30:06 +08:00
eventName: E,
handler: F,
options?: {
immediate?: boolean
immediateArgs?: Parameters<F>
once?: boolean
},
2025-10-23 12:14:03 +08:00
): () => void {
if (!handler) return () => {}
2025-09-24 11:30:06 +08:00
if (!this._eventHandlers.has(eventName)) {
this._eventHandlers.set(eventName, new Set<HandlerWrapper<F>>())
}
const set = this._eventHandlers.get(eventName)!
2025-10-23 12:14:03 +08:00
const wrapper: HandlerWrapper<F> = { fn: handler, once: options?.once ?? false }
2025-09-24 11:30:06 +08:00
if (![...set].some((wrapper) => wrapper.fn === handler)) {
2025-10-23 12:14:03 +08:00
set.add(wrapper)
2025-09-24 11:30:06 +08:00
}
if (options?.immediate) {
try {
handler(...(options.immediateArgs ?? []))
} catch (e) {
console.error(e)
}
}
2025-10-23 12:14:03 +08:00
return () => {
set.delete(wrapper)
// 如果该事件下无监听器,则删除集合
if (set.size === 0) this._eventHandlers.delete(eventName)
}
2025-09-24 11:30:06 +08:00
}
/**
*
* @param eventName
* @param handler
* @example
2025-10-23 12:14:03 +08:00
* eventBus.remove('noArgs', () => {})
2025-09-24 11:30:06 +08:00
*/
2025-10-23 12:14:03 +08:00
remove<E extends keyof Events, F extends Events[E]>(eventName: E, handler: F) {
2025-09-24 11:30:06 +08:00
const set = this._eventHandlers.get(eventName)
if (!set) return
for (const wrapper of set) {
if (wrapper.fn === handler) {
set.delete(wrapper)
}
}
2025-10-23 12:14:03 +08:00
if (set.size === 0) {
this._eventHandlers.delete(eventName)
}
2025-09-24 11:30:06 +08:00
}
/**
*
* @param eventName
* @param args
* @example
2025-10-23 12:14:03 +08:00
* eventBus.notify('noArgs')
* eventBus.notify('greet', 'Alice')
* eventBus.notify('onResize', 1, 2)
2025-09-24 11:30:06 +08:00
*/
2025-10-23 12:14:03 +08:00
notify<E extends keyof Events, F extends Events[E]>(eventName: E, ...args: Parameters<F>) {
2025-09-24 11:30:06 +08:00
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()
}
}