Skip to content

发布订阅的通用实现

现在我们已经看到了如何让售楼处拥有接受订阅和发布事件的功能。假设现在小明又去另一个售楼处买房子,那么这段代码是否必须在另一个售楼处对象上重写一次呢,有没有办法可以让 所有对象都拥有发布—订阅功能呢?

答案显然是有的,JavaScript 作为一门解释执行的语言,给对象动态添加职责是理所当然的 事情。所以我们把发布—订阅的功能提取出来,放在一个单独的对象内:

javascript
const eventBus = {
  clientList: {},
  listen (key, fn) {
    (this.clientList[key] || (this.clientList[key] = [])).push(fn)
  },
  trigger (key, ...args) {
    const fns = this.clientList[key]
  
    if (!fns || fns.length === 0) {
      return
    }
  
    for (let i = 0, l = fns.length; i < l; i++) {
      fns[i].apply(this, args)
    }
  }
}

const installEvent = obj => {
  const keys = Object.keys(eventBus)

  for (let i = 0, l = keys.length; i < l; i++) {
    const key = keys[i]
    obj[key] = eventBus[key]
  }
}

const salesOffices = {}

installEvent(salesOffices)

// A 订阅消息
salesOffices.listen('squareMeter88', function (price, squareMeter) {
  console.log(price, squareMeter)
})

// B 订阅消息
salesOffices.listen('squareMeter110', function (price, squareMeter) {
  console.log(price, squareMeter)
})

// 发布消息
salesOffices.trigger('squareMeter88', 2000000, 88)
salesOffices.trigger('squareMeter110', 3000000, 110)