我们先了解什么是发布-订阅模式,发布-订阅模式它是一种对象间一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都将得到状态的通知。
发布-订阅模式流程如下:
举一个生活中的例子:
张三最近看上一套房子,到售楼处才被告知,该楼盘已售罄。好在售楼MM告诉张三,不久后将有一些尾盘推出,开发商正在办理相关手续,手续办好后便可以购买,但到底什么时候好,目前还没有人知道。
于是张三记下了售楼处的电话,以后每天都会打电话过去询问是不是已经到了购买时间。除了张三,还有李四、王五、小明也会每天向售楼处咨询这个问题。一个星期过后,售楼MM决定辞职,因为厌倦了每天回答1000个相同内容的电话。
当然现实中没有这么笨的销售公司,实际是这样的:张三离开之前,将电话号码留在售楼处。售楼MM答应他,新楼盘一推出就马上发信息通知张三。李四、王五、小明也是一样的,他们的电话号码记录在售楼处的花名册上,新楼盘推出时,售楼MM翻开花名册遍历上面的电话号码,依次发送一条短信通知他们。
上述例子中,发送短信通知就是一个发布-订阅模式,张三、王五等购买者都是订阅者,他们订阅房子开售的消息。售楼处作为发布者,会在合适的时候遍历花名册上的电话号码,依次给购房者发布消息。
上述例子存在的好处有:
回到代码层面上来,发布-订阅能给我们带来以下好处:
了解发布-订阅模式后,再回到mitt身上来。
mitt是一个发布-订阅模式的库,并且它有9k的Star,优点有:
安装:
npm install --save mitt
导入:
// 使用 ES6 模块化
import mitt from 'mitt'
// 使用CommonJs模块化
var mitt = require('mitt')
CDN:
mitt
挂载至全局对象window
。
mitt API方法有:
on
订阅事件;emit
发布事件;off
取消订阅的事件。import mitt from 'mitt'
const emitter = mitt()
// 订阅事件
emitter.on('foo', e => console.log('foo', e) )
// 订阅所有的事件
emitter.on('*', (type, e) => console.log(type, e) )
// 发布事件
emitter.emit('foo', { a: 'b' })
// 清空所有事件
emitter.all.clear()
function onFoo() {}
emitter.on('foo', onFoo) // 订阅
emitter.off('foo', onFoo) // 取消订阅事件
发布-订阅使用场景(包括但不限于):
这有一个小dome可以点击体验:mitt dome。
mitt非常简单,源码也只有100行而且还是使用了TypeScript的情况下。
我去除掉TypeScript类型,将其修改成javaScript实现:
export default function mitt(all){
//使用Map存储注册的事件
all = all || new Map();
return {
all,
on(type, handler) {
const handlers= all!.get(type);
if (handlers) {
handlers.push(handler);
}
else {
all!.set(type, [handler])
}
},
off(type, handler) {
const handlers = all!.get(type);
if (handlers) {
if (handler) {
const index = handlers.indexOf(handler)
handlers.splice(index > -1 ? index : 0, 1);
}
else {
all!.set(type, []);
}
}
},
emit(type, evt) {
let handlers = all!.get(type);
if (handlers) {
handlers.slice().map((handler) => {
handler(evt);
});
}
//判断是否存在"*" 订阅的事件,"*"注册的事件进行兜底
handlers = all!.get('*');
if (handlers) {
handlers.slice().map((handler) => {
handler(type, evt);
});
}
}
};
}
all
就是一个Map
对象,它用于存储订阅事件。
相信大家理解这几行代码没啥难度。
这样我们就学会了一个拥有9k Star库的所有源码。
当然,咱们还能再给它扩展其他方法,如:once
仅订阅一次,我也写过类似的发布-订阅模式medash/event.ts ,有兴趣的同学可以点它看看。
本文先向读者介绍了发布-订阅模式相关理论,再给读者介绍发布-订阅模式社区现成的工具库mitt,最后从mitt的 100行源码中学习到实现发布-订阅模式相关逻辑。
如果我的文章对你有帮助,您的就是对我的最大支持_。
往期文章:http://linglan01.cn/about