實現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);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章