-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
上一节主要讲了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设计模式与开发实践
下一篇
Metadata
Metadata
Assignees
Labels
No labels