const name = '@@EventEmitter' const id_Identifier = '__id__' /** * generate random id */ function randomId() { return Math.random().toString(36).substr(2, 16) } /** * find id * @param id */ function findIndexById(this: CallbackFunc[], id: string) { return this.findIndex((callback) => callback[id_Identifier] === id) } type CallbackFunc = { [id_Identifier]?: string } & ((...dataArray: any[]) => void) export default class EventEmitter { [name]: Record static Events = { global: '*', } constructor() { this[name] = {} } on(event: string, listener: CallbackFunc) { let events = this[name] let container = (events[event] = events[event] || []) let id = randomId() let index = -1 listener[id_Identifier] = id container.push(listener) return () => { index = findIndexById.call(container, id) index >= 0 && container.splice(index, 1) } } off(event: string) { this[name][event] = [] } clear() { this[name] = {} } once(event: string, listener: CallbackFunc) { let self = this let events = self[name] let container = (events[event] = events[event] || []) let id = randomId() let index = -1 let callback: CallbackFunc = function (...dataArray: any[]) { index = findIndexById.call(container, id) index >= 0 && container.splice(index, 1) listener.apply(self, dataArray) } callback[id_Identifier] = id container.push(callback) } emit(event: string, ...dataArray: any[]) { let self = this let events = self[name] let triggers = (events[EventEmitter.Events.global] || []).concat(events[event] || []) triggers.length > 0 && triggers.map((listener) => listener.apply(self, dataArray)) } }