EventBus

70 阅读2分钟

Api

  • all:用于存储所有事件,Map结构,key是事件名称,value是
  • on:给指定事件注册处理事件
    • type string|symbol 事件名称
    • handler function 处理函数
  • off:删除指定事件的事件处理函数
    • type string|symbol 事件名称
    • handler? function 处理函数,省略时删除注册的全部处理函数
  • emit:触发指定事件的所有处理函数
    • type string|symbol 事件名称
    • evt any? 处理函数调用时的参数

对象

分三个:订阅者,发布者,调度中心 all

  • on
    • 订阅者调用此函数,订阅指定事件,传入处理函数
  • off
    • 订阅者调用此函数,删除订阅
  • emit
    • 发布者调用此函数,触发所有订阅者传入的处理函数

调度中心负责存储以上的全部数据

构造函数

class EventBus {
  eventList: Map<string | symbol, Function[]>;
  constructor() {
    this.eventList = new Map();
  }
}

on 添加监听

// 注册事件
  on(event: string | symbol, callback: Function) {
    if (!this.eventList.has(event)) {
      this.eventList.set(event, []);
    }

    this.eventList.get(event).push(callback);
  }

emit 触发通知

遍历触发最好使用 map,因为 map 是生成数组的副本,然后在副本上迭代,这样即使在事件函数中修改了原始数组,也不会影响正在进行的迭代.forEach可能因为修改了原数组导致出问题

var arr = [1, 2, 3]
arr.map(val => {
  if (val > 2) {
    arr.push('a')
  }
  console.log(val)
}) // 1 2 3

// arr 已经变成了 1 2 3 a
arr.forEach(val => {
  if (val === 2) {
    arr.shift() // 遍历到 2 时,删除了 1,然后所有元素相当于前移了,接下来该访问第三个数的,本来是3,但是前移一位,变成了 a
    // 这里直接 arr = [],不会中断后续执行,会正常输出 1 2 3 a
  }
  console.log(val)
}) // 1 2 a
// 触发事件
  emit(event: string | symbol, ...args: any[]) {
    if (this.eventList.has(event)) {
      this.eventList.get(event).map((listener: Function) => listener(...args));
    }
  }

off 注销事件

有 callback 时,注销时可以通过 filter 得到剩下的函数数组,直接set覆盖

// 注销事件
  off(event: string | symbol, callback?: Function) {
    if (this.eventList.has(event)) {
      if (callback) {
        const newEventList = this.eventList.get(event).filter((listener: Function) => listener !== callback);
        this.eventList.set(event, newEventList);
      } else {
        this.eventList.delete(event);
      }
    }
  }

once 只触发一次的 注册监听事件

通过生成新的回调函数 once,在首次调用 emit 时触发这个 once,触发回调后立即销毁 once 的监听(注意如果在回调函数里面又通过once添加了会怎么样呢?会变成on的效果,虽然每次实际添加的都是一个新的回调函数)

// 只执行一次
  once(event: string | symbol, callback: Function) {
    const once = (...args: any[]) => {
      callback(...args);
      this.off(event, once);
    };
    this.on(event, once);
  }

导出

export const bus = new EventBus();
export const Bus = EventBus;