EventEmitter
class EventEmitter {
handlers
constructor() {
this.handlers = new Map()
}
on(eventName, cb) {
if (!this.handlers.has(eventName)) {
this.handlers.set(eventName, [])
}
this.handlers.get(eventName).push(cb)
}
emit(eventName, ...args) {
const callbacks = this.handlers.get(eventName)
if (callbacks) {
// 这里需要对 this.handlers[eventName] 做一次浅拷贝,主要目的是为了避免通过 once 安装的监听器在移除的过程中出现顺序问题
const handlers = callbacks.slice()
handlers.forEach((callback) => {
callback(...args)
})
}
}
off(eventName, cb) {
const callbacks = this.handlers.get(eventName)
if (callbacks) {
const index = callbacks.indexOf(cb)
if (index !== -1) {
callbacks.splice(index, 1)
}
}
}
once(eventName, cb) {
// 对回调函数进行包装,使其执行完毕自动被移除
const wrapper = (...args) => {
cb(...args)
this.off(eventName, wrapper)
}
this.on(eventName, wrapper)
}
}
class EventEmitter {
handlers: Map<string, ((...args: unknown[]) => void)[]>
constructor() {
this.handlers = new Map<string, ((...args: unknown[]) => void)[]>()
}
on(eventName: string, cb: (...args: unknown[]) => void) {
if (!this.handlers.has(eventName)) {
this.handlers.set(eventName, [])
}
this.handlers.get(eventName)!.push(cb)
}
emit(eventName: string, ...args: unknown[]) {
const callbacks = this.handlers.get(eventName)
if (callbacks) {
// 这里需要对 this.handlers[eventName] 做一次浅拷贝,主要目的是为了避免通过 once 安装的监听器在移除的过程中出现顺序问题
const handlers = callbacks.slice()
handlers.forEach((callback) => {
callback(...args)
})
}
}
off(eventName: string, cb: (...args: unknown[]) => void) {
const callbacks = this.handlers.get(eventName)
if (callbacks) {
const index = callbacks.indexOf(cb)
if (index !== -1) {
callbacks.splice(index, 1)
}
}
}
once(eventName: string, cb: (...args: unknown[]) => void) {
// 对回调函数进行包装,使其执行完毕自动被移除
const wrapper = (...args: unknown[]) => {
cb(...args)
this.off(eventName, wrapper)
}
this.on(eventName, wrapper)
}
}
在线演示:
上面包含了一个EventEmitter常用的方法,下面的开源实现提供了更多功能: