JavaScript 设计模式-发布订阅模式

发布订阅模式

  • on: 负责订阅事件, emit负责发布事件, eventMap: 事件名称和事件的映射
class EventEmitter {
  constructor() {
    // eventMap 用来存储事件和监听函数之间的关系
    this.eventMap = {}
  }

  /**
   * # >>>>>>> 注册事件 / 订阅事件
   * type: 这里就代表事件的名称
   * handler: 代表事件, 必须是一个函数
   */
  on(type, handler) {
    if (!(handler instanceof Function)) {
      throw new Error('Must be a Function!')
    }

    // 判断 type 事件对应的队列是否存在
    if (!this.eventMap[type]) {
      // 新建
      this.eventMap[type] = []
    }

    // 将 handler 推入 队列
    this.eventMap[type].push(handler)
  }

  /**
   * # >>>>>>> 发布事件
   * type: 发布事件的名称
   * params: 携带的参数
   */
  emit(type, params) {
    // 事件是被订阅的: 对应的事件队列存在
    if (this.eventMap[type]) {
      this.eventMap[type].forEach((handler, index) => {
        // 传递params
        handler(params)
      })
    }
  }

  /**
   * # 要卸载的 事件名称 对应的函数: event.off('event-name-a',handleA), 把 event-name-a 对应的 handleA 卸载,其他事件保留
   * type: 事件的名称
   * handler: 代表事件, 必须是一个函数
   */
  off(type, handler) {
    if (this.eventMap[type]) {
      this.eventMap[type].splice(this.eventMap[type].indexOf(handler) >>> 0, 1)
    }
  }
}

const myEvent = new EventEmitter()

const testHandler = function (params) {
  console.log(`test事件被触发了,testHandler 接收到的入参是${params}`)
}

// 监听 test 事件
myEvent.on('test', testHandler)
myEvent.on('testb', testHandler)

// 在触发 test 事件的同时,传入希望 testHandler 感知的参数
myEvent.emit('test', 'newSate aaa')
myEvent.emit('testb', 'newSate bbb')

console.info(myEvent)

posted @ 2020-10-27 15:41  荣光无限  阅读(150)  评论(0编辑  收藏  举报