一、发布订阅
步骤:
- 通过 button.addEventListener('click', fn) 监听/订阅事件
- 用户点击触发 button.dispatchEvent(...'click') 执行,即触发事件
- fn 被调用
特点:
- api 提供了 addEventListener / on / subscribe
- api 提供了 dispatchEvent / emit / trigger
- api 提供了 removeEventListener / off / unsubscribe 满足上述条件的对象被称为 EventEmitter,实现了发布订阅模式
二、EventEmitter的实现
class EventEmitter {
constructor() {
this.queue = { /* xxx: [] 无法初始化 */ }
}
addEventListener(name, fn) {
this.queue[name] = this.queue[name] || [] // 初始化
this.queue[name].push(fn)
}
dispatchEvent(name, ...args) {
this.queue[name]?.forEach(fn => fn.call(undefined, ...args))
}
removeEventListener(name, fn) {
if (this.queue[name] === undefined) { return }
const index = this.queue[name].indexOf(fn)
if (index >= 0) { this.queue[name].splice(index, 1) }
}
}
三、EventEmitter的使用
const obj = new EventEmitter()
const fn = () => console.log('hi')
obj.addEventListener('xxx', fn)
obj.dispatchEvent('xxx')
obj.removeEventListener('xxx', fn)
四、发布订阅总结
发布订阅解决了什么问题?
所有异步任务都可以用发布订阅来管理
先订阅成功事件和失败事件
xhr.on('load'); xhr.on('error')
再在任务完成时触发成功或失败事件
xhr.emit('load'); xhr.emit('error')
是一个通用的异步任务管理方案
缺点是什么?
事件少时还行;但当事件过多时,很难管理