原文链接跳转

好长时间没有写文章了,刚好年底了,就把前段时间在项目中用到和学到的技术方案写下来,一个是发布订阅模式,还有一个就是队列在项目中的应用了,关于队列在下一篇文章。

之前也有了解过发布订阅,但在项目中实际使用也是第一次,这个项目重构,小组大佬引入了这个方案!!这次也算是学习到了,如何把一些概念引用到项目中,合理解决软件项目的实际问题。[以下内容参考:javascript设计模式与开发实践]()

常见的订阅发布

在我们的日常生活中,就可以找到订阅发布,例如我们在B站中常用的的订阅服务,你在上面订阅了一个up主,当up主更新了视频之后,你就会收到对应的通知。当然,这个通知的形式是有各种各样的,这个就是我们这里要讨论的。订阅者 ——> 更新数据 ——> 发布者通知,这样的一个流程,就是最最在生活中一个常见的例子了。

那在前端项目中,我们是否有用到发布订阅嘛?

document.addEventListener('click', ()=> {console.log('一号监听器')})

document.addEventListener('click', ()=> {console.log('二号监听器')})

以上代码对点击事件进行了两次监听,它们互相不会覆盖,这也是在前端项目中,最常见的一个例子🌰。从这个代码中,我们可以发现,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})

好啦,一个简易的订阅发布器就可以啦!可以试试这一段代码,是不是已经可以直接使用了,满满的成就感。一般在订阅发布器都是挂载在全局下的,那么我们只需要把以上的函数封装成一个函数或者一个类就可以啦!!

是不是感觉以上的代码少了一点什么?订阅和发布都有了,如果我们想取消订阅怎么办,这里我不继续说了,希望你自己可以去翻书或者查资料,别人给的毕竟不如自己做的,取消订阅的具体实现,留待大家思考吧。至于如何在项目中使用,这个基本也不用说,因为在你的日常项目中,你就有在用哦!![建议直接看:javascript设计模式与开发实践]()

使用场景和解决的问题

下面要说到的,就是订阅发布的使用场景,和解决的问题。当然,其实这可以归纳为一个问题。

这里我列举几个使用的场景:

1. 跨模块或跨组件的通信
2. 全局的消息通知
......等

更多的场景想不出来了。。。。。,希望有人可以补充。我也是看书总结的,就不复制粘贴了,订阅发布模式的作用有两点:

1.解耦; 
2.避免硬编码;

解藕:避免项目不同的模块和组件的代码复杂度,多个模块的代码交织在一起;避免硬编码:不需要通过变量手动来强制修改一些状态;

对于设计模式,重要的是理解其思想,然后尝试是否可以运用到项目中去,因为只有使用的知识,才是活知识嘛。好了,我继续去看书了。


HerryLo
238 声望11 粉丝

喜爱JavaScript和NodeJs;