Skip to content

发布-订阅模式

一、什么是发布-订阅模式

二、怎么实现发布-订阅模式

2.1. 设计发布-订阅模式api

2.1.1. 怎么处理发布以及订阅之间的关系

2.1.1. 怎么实现订阅

2.1.1. 怎么实现发布

2.2. 代码实现

typescript
class EventBus{
  // 存储事件-动作的对应关系
  private events: Map<string,any> = new Map();
  constructor(events?: Map<string, Function>){
    this.events = events || new Map();
  }

  /**
   * 增加订阅事件,并向订阅事件中添加动作/方法
   * @param event 事件类型
   * @param fn 要添加的动作/方法
   */
  on(event:string, fn:any): void{
    const e = this.events.get(event);

    if (!e) {
      this.events.set(event, [fn]);
    } else {
      e.push(fn);
    }
  }

  /**
   * 删除对应的订阅事件
   * @param event 要删除的订阅事件
   */
  off(event:string): void{
    this.events.delete(event);
  }

  /**
   * 发布事件,所有订阅此事件的动作均可以获取到消息
   * @param event 要发布的事件
   * @param args 向动作/方法中要传递的数据
   */
  emit(event: string, ...args: any[] ): void{
    const e = this.events.get(event);

    if (!e) {
      return;
    } else {
      for (let i = 0; i < e.length; i++) {
        e[i].apply({ key: 'this is key' }, args);
      }
    }
  }
}

// 示例话
const eventBus = new EventBus();

// 订阅/监听『print-year』事件,待事件发布之后便可获取到事件传递来的参数
eventBus.on('print-year', (date: Date) => {
  console.log(`我关注的是当前年份:${date.getFullYear()}`);
})
eventBus.on('print-month', (date: Date) => {
  console.log(`我关注的是当前月份:${date.getMonth()}`);
})
eventBus.on('print-date', (date: Date) => {
  console.log(`我关注的是当前日期:${date.getDate()}`);
})

// 发布/触发事件并传递参数
eventBus.emit('print-year', new Date());
eventBus.emit('print-month', new Date());
eventBus.emit('print-date', new Date());

// 取消订阅『print-year』事件,对应事件再次发布不会收到信息
eventBus.off('print-year');

// 发布/触发事件并传递参数
eventBus.emit('print-year', new Date());
eventBus.emit('print-month', new Date());
eventBus.emit('print-date', new Date());