什么是发布-订阅模式?
1、说一下定义噻
发布-订阅模式其实是一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到状态改变的通知。
2、简单的流程
订阅者将自己订阅的事件注册到调度中心,当发布者发布该事件到调度中心,当该事件触发时,由调度中心统一调度订阅者注册到调度中心的处理代码。
3、举个例子吧
我们在微博上关注自己喜欢的爱豆时,爱豆发微博的行为就可以看做是一个简单的发布-订阅模式。我们是订阅者,爱豆是发布者,微博平台是调度中心。当爱豆发送微博到微博平台,平台会将这条微博推送到我们自己的微博上。
如何实现?
1、思路
- 创建对象(调度中心)
- on 方法用来把函数都存放在调度中心(订阅这事件注册到调度中心)
- emit 方法取到arguments里第一个当做event,根据event值去执行调度中心的事件(发布者发布事件到调度中心,调度中心开始处理代码)
- off 方法可以根据event值取消订阅(取消订阅)
- once 方法只监听一次,调用完毕后删除缓存函数(订阅一次)
2、实现
let bus = {
list: {}, // 调度中心
on(event, fn) { // 订阅
let self = this;
// 存放订阅的事件
// 该事件存在则直接存放 该事件不存在则开辟数组开始存放
(self.list[event] || (self.list[event] = [])).push(fn);
return self;
},
once(event, fn) { // 订阅一次
let self = this;
function on() {
self.off(event, on);
fn.apply(self, arguments);
}
on.fn = fn;
self.on(event, on);
return self;
},
emit(...args) { // 发布
let self = this;
// 通过shift拿到事件名称
let event = args.shift();
// 通过事件名称拿到对应的存放事件
let fns = [...self.list[event]];
if (!fns || (fns.length === 0)) {
return false;
}
fns.forEach(fn => {
fn.apply(self, args);
});
return self;
},
off(event, fn) { // 取消订阅
let self = this;
let fns = self.list[event];
if (!fns) {
return false;
}
if (!fn) {
// 如果没有传递fn 将event对应的缓存列表清空
fns && (fns.length = 0);
} else {
let cb;
for (let i = 0, i < fns.length; i < length; i++) {
cb = fns[i];
if (cb === fn || cb.fn === fn) {
fns.split(i, 1);
}
}
}
return self;
}
};
小结一下
本来简单的捋了捋思路,有个大概印象,也加深自己对于发布-订阅模式的印象。同时也有一些疑问,对于只订阅一次那里始终存疑,感觉有点绕不明白,我这里也多多思考,也希望大家多多批评指教。