主题
发布–订阅模式说明(对应 EventEmitter)
- Dep(事件中心):独立的调度中心,负责维护订阅关系并广播事件
- Sub(订阅者):注册到事件中心的回调函数,在事件触发时执行
- Pub(发布者):主动向事件中心发布事件的调用方
Dep 是一个
事件调度中心,负责维护事件与订阅者的映射关系。 它对外提供 on / emit / off 等接口,用于解耦发布者与订阅者。Sub 是通过 on 注册到 Dep 的事件回调函数, 平时不执行,仅在对应事件被发布时由 Dep 调度执行。
Pub 是事件的发布者,通过调用 emit 向 Dep 发布事件, 接收到事件后通知所有订阅该事件的 Sub 执行。
Dep 负责调度,Sub 负责执行,Pub 负责触发。
EventEmitter
js
// 调度中心 Dep
class EventEmitter {
constructor() {
// 存储事件及其对应的回调函数列表
this.events = {}
}
// 订阅事件 Sub
on(eventName, ...callback) {
if (!this.events[eventName]) {
this.events[eventName] = []
}
callback.forEach(item => {
if(! Array.isArray(item)) {
item = [item]
}
this.events[eventName].push(...item)
})
}
// 发布事件 Pub
emit(eventName, data) {
const callbacks = this.events[eventName]
if (callbacks) {
callbacks.forEach(callback => callback(data))
}
}
// 取消订阅事件 Sub
off(eventName, ...callback) {
if(! this.events[eventName]) return false
if(!callback) {
delete this.events[eventName]
return true
}
callback.forEach(back => {
if(typeof back === 'function') {
this.events[eventName] = this.events[eventName].filter(item => item !== back)
return true
}
})
return false
}
}调用 EventEmitter
js
const eventBus = new EventEmitter()
const isSwitch = boolean => (!!boolean ? "开" : "关")
const controlHomeAppliance = (onOff, homeApplianceName) => {
console.log(`开关改变,当前${homeApplianceName}的模式为${isSwitch(onOff)}`)
}
const lightCallBack = onOff => controlHomeAppliance(onOff, '电灯')
const television = onOff => controlHomeAppliance(onOff, '电视')
// 将事件名为 switch 的函数收集起来
eventBus.on("switch", [lightCallBack, television])
// 删掉其中 switch 事件名中其中已经收集的一个函数
eventBus.off("switch", television)
// 一秒钟之后通知已经收集的函数执行
setTimeout(() => {
eventBus.emit("switch", true)
}, 1000)