# Javascript项目中使用 - 订阅发布模式
作者:HerryLo (opens new window) 博客原文链接 (opens new window)
好长时间没有写文章了,刚好年底了,就把前段时间在项目中用到和学到的技术方案写下来,一个是发布订阅模式,还有一个就是队列在项目中的应用了,关于队列在下一篇文章。
之前也有了解过发布订阅,但在项目中实际使用也是第一次,这个项目重构,小组大佬引入了这个方案!!这次也算是学习到了,如何把一些概念引用到项目中,合理解决软件项目的实际问题。以下内容参考:javascript设计模式与开发实践
# 常见的订阅发布
在我们的日常生活中,就可以找到订阅发布,例如我们在B站中常用的的订阅服务,你在上面订阅了一个up主,当up主更新了视频之后,你就会收到对应的通知。当然,这个通知的形式是有各种各样的,这个就是我们这里要讨论的。订阅者 ——> 更新数据 ——> 发布者通知,这样的一个流程,就是最最在生活中一个常见的例子了。
那在前端项目中,我们是否有用到发布订阅嘛?
document.addEventListener('click', ()=> {console.log('一号监听器')})
document.addEventListener('click', ()=> {console.log('二号监听器')})
2
3
以上代码对点击事件进行了两次监听,它们互相不会覆盖,这也是在前端项目中,最常见的一个例子🌰。从这个代码中,我们可以发现,addEventListener
的作用就是订阅(监听),但这里有两个监听,说明进行多次监听时,即使监听的都是click
类型的事件,但也不会被覆盖,说明有一个列表,帮我们把监听都进行了保存,然后再同时触发。好的,我们也依据我们分析的,来编写一个简易的订阅发布器(监听发布器)。
# 实现简易的订阅发布
首先需要一个订阅器(监听器),然后需要一个列表进行缓存,最后需要通知触发(发布):
// 缓存
let _cache = {};
// 监听器(订阅)
function addLister(type, fn) {
if(!_cache[type]) {
// 类型不存在,就是创建一个缓存列表
_cache[type] = [];
}
// 回调放入缓存
_cache[type].push(fn);
}
// 触发器(发布)
function trigger(type, option = {}) {
if(!_cache[type]) {
// 类型不存在,直接结束
return false;
}
let list = _cache[type];
for(let i = 0 ; i < list.length ; i++) {
// 遍历缓存列表,发布消息通知
list[i](option);
}
}
// 订阅
addLister("click", (e)=> {console.log(e.a);});
addLister("click", (e)=> {console.log(e.b);});
// 发布
trigger("click", {a: 1, b: 2})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
好啦,一个简易的订阅发布器就可以啦!可以试试这一段代码,是不是已经可以直接使用了,满满的成就感。一般在订阅发布器都是挂载在全局下的,那么我们只需要把以上的函数封装成一个函数或者一个类就可以啦!!
是不是感觉以上的代码少了一点什么?订阅和发布都有了,如果我们想取消订阅怎么办,这里我不继续说了,希望你自己可以去翻书或者查资料,别人给的毕竟不如自己做的,取消订阅的具体实现,留待大家思考吧。至于如何在项目中使用,这个基本也不用说,因为在你的日常项目中,你就有在用哦!!建议直接看:javascript设计模式与开发实践
# 使用场景和解决的问题
下面要说到的,就是订阅发布的使用场景,和解决的问题。当然,其实这可以归纳为一个问题。
这里我列举几个使用的场景:
1. 跨模块或跨组件的通信
2. 全局的消息通知
......等
更多的场景想不出来了。。。。。,希望有人可以补充。我也是看书总结的,就不复制粘贴了,订阅发布模式的作用有两点:
1.解耦;
2.避免硬编码;
2
解藕:避免项目不同的模块和组件的代码复杂度,多个模块的代码交织在一起;避免硬编码:不需要通过变量手动来强制修改一些状态;
对于设计模式,重要的是理解其思想,然后尝试是否可以运用到项目中去,因为只有使用的知识,才是活知识嘛。好了,我继续去看书了。
ps: 微信公众号:Yopai,有兴趣的可以关注,每周不定期更新。不断分享,不断进步
男性,武汉工作,会点Web,擅长Javascript.
技术或工作问题交流,可联系微信:1169170165.