|
import { EventHandler } from "./types" |
|
|
|
export class AGEventEmitter<T> { |
|
private readonly _eventMap: Map<keyof T, EventHandler<any[]>[]> = new Map() |
|
|
|
once<Key extends keyof T>(evt: Key, cb: T[Key]) { |
|
const wrapper = (...args: any[]) => { |
|
this.off(evt, wrapper as any) |
|
;(cb as any)(...args) |
|
} |
|
this.on(evt, wrapper as any) |
|
return this |
|
} |
|
|
|
on<Key extends keyof T>(evt: Key, cb: T[Key]) { |
|
const cbs = this._eventMap.get(evt) ?? [] |
|
cbs.push(cb as any) |
|
this._eventMap.set(evt, cbs) |
|
return this |
|
} |
|
|
|
off<Key extends keyof T>(evt: Key, cb: T[Key]) { |
|
const cbs = this._eventMap.get(evt) |
|
if (cbs) { |
|
this._eventMap.set( |
|
evt, |
|
cbs.filter((it) => it !== cb), |
|
) |
|
} |
|
return this |
|
} |
|
|
|
removeAllEventListeners(): void { |
|
this._eventMap.clear() |
|
} |
|
|
|
emit<Key extends keyof T>(evt: Key, ...args: any[]) { |
|
const cbs = this._eventMap.get(evt) ?? [] |
|
for (const cb of cbs) { |
|
try { |
|
cb && cb(...args) |
|
} catch (e) { |
|
|
|
const error = e as Error |
|
const details = error.stack || error.message |
|
console.error( |
|
`[event] handling event ${evt.toString()} fail: ${details}`, |
|
) |
|
} |
|
} |
|
return this |
|
} |
|
} |
|
|