const eventbus = {
map: {
},
on: ( name , fn ) => {
eventbus.map[ name ] = eventbus.map[name] || []
eventbus.map[name].push(fn)
},
emit: ( name , data ) => {
const q = eventbus.map[name]
if(!q) return
q.map(f => f.call(undefined,data))
},
off: ( name , fn ) => {
const q = eventbus.map[name]
if(!q) {return}
const index = q.indexOf(fn)
if(index < 0 ) {return}
q.splice( index , 1 )
}
}
eventbus.on('click',console.log)
eventbus.on('click',console.error)
setTimeout( () => {
eventbus.emit('click' , 'young')
} , 3000)
也可以用 class 来实现
class Eventbus {
constructor(){
this.map = {}
}
on( name , fn ) {
this.map[ name ] = this.map[name] || []
this.map[name].push(fn)
}
emit ( name , data ) {
const q = this.map[name]
q?.map(f => f.call(undefined,data))
}
off ( name , fn ) {
const q = this.map[name]
if(!q) {return}
const index = q.indexOf(fn)
if(index < 0 ) {return}
q.splice( index , 1 )
}
}
const e = new Eventbus()
e.on('click',console.log)
e.on('click',console.error)
setTimeout( () => {
e.emit('click' , 'young')
} , 3000)
发布订阅模式的特点:
- api 提供了 on/off/emit (或其他意思一样的表达),满足上述条件会被称为 EventEmitter,实现了发布订阅模式。
本质是把回调函数放在队列里,等待被逐个调用 发布订阅解决了什么问题?
- 所有异步任务都可以用发布订阅来管理
- 先订阅成功事件和失败事件
- 再在任务完成得时触发成功或失败案件
- 是一个通用得异步任务管理方案
- 可以用于将代码解耦
缺点是
- 事件过多时,很难管理