1. 程式人生 > 實用技巧 >JavaScript 設計模式-釋出訂閱模式

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)