EventEmiter
发布订阅模式(本质上是一种设计模式)
步骤
1.通过 button.addEventListener(‘click’, fn) 监听/订阅事件
2.用户点击触发 button.dispatchEvent(…‘click’) 执行,即触发事件
3.fn 被调用
-
- 如何取消监听/订阅?- button.removeEventListener
-
- 如果多次监听会怎样?- 按监听顺序依次执行 fn1、fn2
-
- 如果将第 1、2 步颠倒过来会怎样?- 会使得 fn 不被执行
-
- button 是怎么得到 addEventListener 方法的?- 通过原型链得到的
实例(考虑上事件名 用class写)
class EventEmitter {
constructor() {
this.queue = { /* xxx: [] 无法初始化 */ }
}
addEventListener(name, fn) {
this.queue[name] = this.queue[name] || [] // 初始化
this.queue[name].push(fn)
}
dispatchEvent(name) {
this.queue[name]?.forEach(fn => fn())
}
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) }
}
}
调用
const api = new EventEmitter()
api.addEventListener('user:success', f1)
api.addEventListener('user:fail', f2)
也可以直接用ajax函数对象来
ajax.addEventListener('user:success', (data) => console.log(data))
ajax.addEventListener('user:fail', (error) => console.error(error))
// 会在未来调用
// ajax.dispatchEvent('user:success', data)
// 或
// ajax.dispatchEvent('user:fail', error)
summary
发布订阅模式的特点
api 提供了 addEventListener / on / subscribe
api 提供了 dispatchEvent / emit / trigger
api 提供了 removeEventListener / off / unsubscribe
满足上述条件的对象被称为 EventEmitter,实现了发布订阅模式
把回调(函数)放在队列(数组)里,等待被逐个调用
发布订阅解决了什么问题
所有异步任务都可以用发布订阅来管理
是一个通用的异步任务管理方案但同时 事件过多时,会很难管理