实现eventEmmiter,发布-订阅 模式 (on, emit, off)

/*
 * @Date: 2024-03-14 15:46:52
 * @Description: Modify here please
 */
interface SubscribeEvent {
  fn: Function;
  once: boolean;
}

class EventEmmiter {
  subscribes: Map<string, Array<SubscribeEvent>>;

  constructor() {
    this.subscribes = new Map();
  }

  addEvent(type: string, callback: Function, once: boolean = false) {
    const sub = this.subscribes.get(type) || [];
    sub.push({ fn: callback, once });
    this.subscribes.set(type, sub);
  }
  /**
   * 事件订阅
   * @param type 订阅的事件名称
   * @param callback 触发的回调函数
   */

  on(type: string, callback: Function) {
    this.addEvent(type, callback);
  }
  /**
   * 发布事件
   * @param type 发布的事件名称
   * @param args 发布事件的额外参数
   */
  emit(type: string, ...args: Array<any>) {
    const sub = this.subscribes.get(type) || [];
    const context = this;

    sub.forEach(({ fn }) => {
      fn.call(context, ...args);
    });

    const newSub = sub.filter((item) => !item.once);
    this.subscribes.set(type, newSub);
  }
  /**
   * 取消订阅
   * @param type 取消订阅的事件名称
   * @param callback 取消订阅的具体事件
   */
  off(type: string, callback: Function) {
    const sub = this.subscribes.get(type);

    if (sub) {
      const newSub = sub.filter(({ fn }) => fn !== callback);
      this.subscribes.set(type, newSub);
    }
  }

  // 只订阅一次
  // 我们使用过发布-订阅都应该知道发布-订阅直接一次订阅,即这个订阅者只会被通知一次。下面,我们来增加这个操作。
  // 思路:我们的订阅者需要具有once的属性,来进行判断,并且,在每一次emit后,我们需要把once事件清除。
  once(type: string, callback: Function) {
    this.addEvent(type, callback, true);
  }
}

const eventEmmiter = new EventEmmiter();

// eventEmmiter.once('notice',() => {
//   console.log('只订阅一次');
// })

// const publish = (a,b) => {
//   const sum = a + b
//   console.log(a,b+'两数之和为' + sum);
// }

// eventEmmiter.on('notice',publish);

// eventEmmiter.emit('notice',2,3);
// eventEmmiter.emit('notice',4,5);
posted @ 2024-03-14 15:52  simple-love  阅读(82)  评论(0编辑  收藏  举报