Skip to content

B.分布式事件 #2

@Akiq2016

Description

@Akiq2016

上一节主要讲了what & why,了解的JavaScript异步事件的工作方式。但是在实践中,我们怎么处理这些异步事件?

PubSub模式

首先什么是Publish发布-Subscribe订阅 模式?比如我们需要监控用户点击 document.body 的动作,但是我们没办法预知用户将在什么时候点击。所以我们订阅 document.body 上的 click 事件,当 body 节点被点击时,body 节点便会向订阅 者发布这个消息。

document.body.addEventListener( 'click', () => { console.log(2) }, false )
document.body.click() // 模拟用户点击

再就近举个例子。我在GitHub上建立了asyn-programming-with-JavaScript这个项目,右上角有watch | star | fork 选项。watch是个订阅按钮,如果你选择了watching,则订阅该项目的所有动态,一有更新就会发邮件通知你。这个模式的好处就在于低耦合,两个“模块”毫无联系,各干各的。

虽然两边不太清楚彼此的细节,但这不影响它们之间相互通信。当有新的订阅者出现时,发布者的代码不需要任何修改;同样发布者需要改变时,也不会影响到之前的订阅者。只要之前约定的事件名没有变化,就可以自由地使用它们。

除了DOM事件,我们还会经常实现一些自定义的事件,这种依靠自定义事件完成的PubSub模式可以用于任何 JavaScript 代码中。写一个简陋的例子:

class PubSub {
  constructor () {
    // key <eventType>: value <subscribeList>[]
    this.handlers = {}
  }
  on (eventType, handler) {
    if (!(eventType in this.handlers)) this.handlers[eventType] = []
    this.handlers[eventType].push(handler)
  }
  emit (eventType, ...handlerArgs) {
    this.handlers[eventType].forEach(v => {v(...handlerArgs)})
  }
  remove (eventType, handler) {
    // without giving a specific handler, remove the whole handler list's item
    // don't pass anonymous function as handler when binding
    if (!handler) {
      this.handlers[eventType].length = 0
    } else {
      const key = this.handlers[eventType].findIndex(v => v === handler)
      if (key !== -1) this.handlers[eventType].splice(key, 1)
    }
  }
}

var test1 = new PubSub()
let fn1 = (...data) => console.log( data) 
test1.on('event1', fn1)
test1.on('event1', (...data) => console.log(`2 + ${data}`) )
test1.emit('event1', '我是参数1', '我是参数2', '我是参数3')
test1.remove('event1', fn1)

PubSub模式不适用于一次性事件,一次性事件要求对异步函数执行的一次性任务的两种结果(完成任务或任务失败)做不同的处理。用于解决一次性事件问题的工具叫做Promise。

学习链接:
JavaScript设计模式与开发实践

下一篇

C.Promise 对象

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions