发布\订阅模式:
在软件架构中,发布-订阅是一种消息范式,消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者)。而是将发布的消息分为不同的类别,无需了解哪些订阅者(如果有的话)可能存在。同样的,订阅者可以表达对一个或多个类别的兴趣,只接收感兴趣的消息,无需了解哪些发布者(如果有的话)存在。 有着松耦合、可拓展性强等优点。
这里是一个pub/sub的简单实现:
class EventEmitter {
constructor(){
//observers是一个对象,形式如下:
// {
// chA: [fnA1, fnA2, ...],
// chB: [fnB1, fnB2, fnB3, ...]
// }
// 其中 chA,chB,对应不同频道, fn是每个频道 里面的回调函数
// 订阅、发布: 其实就是往 observers 里面写入回调函数(fn), 以及遍历执行回调函数的过程(fn(arg))
// 订阅 : on('foo', fn)表示 订阅了 频道 foo ,如果 foo频道有消息推送, 就触发回调函数
// 发布: trigger('foo', 'hello')表示 发送一条消息 hello 到 foo 频道,
// 这样 订阅了 foo频道的所有 订阅者 都可以接收到 其数据
this.observers = {}
}
on(channel, f) {
let key = channel
if (Array.isArray(this.observers[key])) {
this.observers[key].push(f)
} else {
this.observers[key] = [f]
}
}
trigger(channel, ...args) {
let _observer = this.observers[channel]
if (!_observer || _observer.length === 0) {
return
}
for (let fn of _observer) {
fn(...args)
}
}
off(channel) {
this.observers[channel] = null
}
}
// 其使用 方式如下
var e = new EventEmitter()
e.on('a', (data) => {
console.log('a data', data)
})
e.on('b', (data) => {
console.log('b data', data)
})
e.trigger('a', 'hello')
e.trigger('b', {
x: 2,
y: 3
})
e.off('a')
结论:
发布\订阅模式的实现很简单, 主要有三部分构成:
- 一个消息中心:observers 用于存储每个订阅的回调函数
- 一个订阅函数: on 用于往 消息中心写入对应频道的监听回调函数
- 一个发布函数:trigger 发布消息, 触发对应频道的所有回调函数,并将数据作为回调函数的参数 传给了订阅者
网友评论