js发布订阅,为什么要将handler包装一层?

看到别人写的EventHub,在监听事件的时候,他会给参数handler套一层new EventListener(),这样做的好处是什么?不将handler抽象成listener也同样可以实现,为什么要多此一举?

export class EventHub<E extends Emiter> {
  private cached: { [name in keyof E]: EventListener[] } = {} as any

  /**
   * @param: 监听的事件名
   * @param: 事件的处理函数, 在事件触发时会被调用
  */
  public on<N extends keyof E>(eventName: N, handler: Handler<E[N]>) {
    if (!handler) { throw new Error('invaild handler') }
    if (!this.cached[eventName]) { this.cached[eventName] = [] }
    const listener = new EventListener(eventName as string, handler, this)
    this.cached[eventName].push(listener)
  }



  /**
   * @param eventName: 触发事件的名称
  */
  public emit<N extends keyof E>(eventName: N, data: E[N] = null) {
    const listeners = this.cached[eventName]
    if (!eventName) { throw new Error('invaild eventName') }
    listeners.forEach((listener) => {
      listener.handler.call(this, data)
    })
  }


  /**
   * @param eventName: 注销事件的名称
   * @param target: 需要注销的事件
   * 不传入 target 默认注销整个事件
  */
  public off<N extends keyof E>(eventName: N, target?: EventListener): boolean {
    if (!this.cached[eventName]) { return false }
    if (!target) {
      this.cached[eventName] = [];
      delete this.cached[eventName];
      return true;
    }
    for (let listeners = this.cached[eventName], i = 0; i < listeners.length; i++) {
      const listener = listeners[i]
      if (listener !== target) { continue }
      this.cached[eventName] = this.cached[eventName].filter((l) => {
        return l !== listener
      })
      listener.distory()
    }
    if (this.cached[eventName].length === 0) {
      delete this.cached[eventName]
      return true
    }
    return false
  }
}
阅读 1.2k
1 个回答

基础的发布订阅模式是不需要对handler进行封装的,这里使用EventListener类对handler进行封装可能是对handler进行统一管理或者使用前的处理,这在复杂项目中很常见

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题