EventEmitter 用法

300 阅读1分钟
一、发布订阅

步骤:

  1. 通过 button.addEventListener('click', fn) 监听/订阅事件
  2. 用户点击触发 button.dispatchEvent(...'click') 执行,即触发事件
  3. 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')

是一个通用的异步任务管理方案

缺点是什么?

事件少时还行;但当事件过多时,很难管理