主题
发布订阅模式
1. 什么是发布订阅模式?
发布订阅模式是⼀种消息范式,消息发送者(发布者)不会将消息直接发送给特定的接受者(订阅者),⽽是将发布的消息分为不同 的类别,通过⼀个中间的消息代理来调度消息,发布者⽆需了解有哪些订阅者存在。同样的,订阅者也只接受⾃⼰感兴趣的那⼀类消息,⽆ 需了解发布者是否存在。 发布者和订阅者都不知道彼此的存在,是完全的松耦合。
自己理解一下就是: 发布-订阅模式其实是一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到状态改变的通知。
2. 发布订阅模式可以解决什么问题?
作用其实就是将发布者和订阅者解耦了(代码解耦),在实际开发中,经常会遇到某个方法内处理很多的逻辑,最简单的就是直接在方法内直接写。这种是高度耦合的面向过程的写法。对于代码维护不友好。
而发布-订阅模式就是将两者分离。我触发了某个事件(这里我们将触发该方法定义为事件),我只向调度中心通知,我并不知道调度中心内会怎么处理,有多少个人响应。我只管通知。 而订阅者只管在调度中心订阅,有人调用它才响应。
例如: vue中的自定义事件,on
,$emit
缺点:创建订阅者要消耗一定的事件和内存。过度使用,会导致程序难以跟踪维护。
3. 发布订阅模式里面的概念
有三个角色,订阅者
、消息调度中心
,发布者
若把发布订阅想成一个杂志的发布订阅,则可以这么理解三者的关系:
- 订阅者:相当于用户,我在中心订阅了这分杂志;
- 消息调度中心:杂志社;
- 发布者:相当与某个杂志负责人,他来中心这注册一个的杂志;
4. 实现发布订阅
4.1 思路
_events
:调度中心 on
订阅: 方法用来把函数都存放在调度中心(订阅这事件注册到调度中心) emit
发布:方法取到arguments里第一个当做event,根据event值去执行调度中心的事件(发布者发布事件到调度中心,调度中心开始处理代码) off
解绑: 方法可以根据event值取消订阅(取消订阅) once
触发一次:方法只监听一次,调用完毕后删除缓存函数(订阅一次)
4.2 代码实现
js
class PubSub {
_events = {} // 事件中心
// 订阅
on(event,callback){
if(!this._events) {
this._events = {};
};
if(this._events[event]) {
this._events[event].push(callback)
}else {
this._events[event] = [callback]
}
}
// 发布
emit(event,...arg){
if(this._events && this._events[event]) {
this._events[event].forEach(cb=>{
cb(...arg)
})
}
}
// 解绑 cb指的是可以单独解绑某个事件
off(event,cb) {
if(this._events&& this._events[event]) {
this._events[event] = this._events[event].filter(item=> (item!== cb && item.fn !== cb))
}
}
// 只会触发一次
once(event,callback) {
let one = (...arg)=>{
callback(...arg) // 先发布
this.off(event) // 再解绑 这里因为emit里面发布的是one函数,所以解绑也得解绑one
}
// 为了解绑成功,需要将传进来的回调函数也存起来
one.fn = callback;
this.on(event,one)
}
}
module.exports = PubSub