订阅发布模式的介绍

发布订阅模式,它定义了一种一对多的关系,可以使多个观察者对象对一个主题对象进行监听,当这个主题对象发生改变时,依赖的所有对象都会被通知到。

在生活中我们常常遇到这样一种情况,我们在使用新闻APP看新闻的时候,每个人喜欢的新闻类型各不一样,比如我喜欢NBA,但是我们总不可能一天24小时在手机上一遍又一遍的刷新,我们就会去新闻频道中选择NBA专栏来收藏,当勇士或者湖人有最新消息,就会通知我们去观看。

当然从上面的场景中是一个典型的发布订阅模式,APP的NBA专栏属于发布者,像我一样广大爱好篮球的小伙伴梦就属于订阅者,当一有最新的消息,它们就会发布给我们。

实际用途

1.在jquery中很多地方都有发布订阅的踪迹,例如事件中on和trigger中封装的方法。

2.尤大大的Vue,中子父组件通信使用的emit()和on()方法,使得组件得到解耦,开发更加高效。

如何实现订阅发布模式

1、首先想好谁是发布者(比如上边的APP的NBA专栏就是发布者);

2、然后给发布者添加一个缓存列表,用于存放回调函数来通知订阅者(比如上面的我们球迷爱好者收藏了NBA专栏,相当于向发布者注入了通知我们的函数);

3、最后就是发布消息,发布者遍历这个缓存列表,依次触发订阅的函数。

表捉急,端起小板凳,先看一下这个简单的发布订阅模式:

let NBAcol={};//自定义一个NBA专栏对象
NBAcol.list=[];// 这里放一个列表用来缓存订阅者的回调函数
NBAcol.on=function(fun){this.list.push(fun); //把fn先存到列表中
};
//发布事件
NBAcol.emit=function(){this.list.forEach(cb => {cb.apply(this, arguments);});// 当发布的时候再把列表里存的函数依次执行
};
//小明的订阅NBA专栏
NBAcol.on(function(team){console.log("我订阅的球队是:"+team)
})
//小李的订阅NBA专栏
NBAcol.on(function(team){console.log("我订阅的球队是:"+team)
})
NBAcol.emit('湖人');
NBAcol.emit('勇士');
/*
我订阅的球队是:湖人;
我订阅的球队是:湖人;
我订阅的球队是:勇士;
我订阅的球队是:勇士;
*/
复制代码

上面就实现了一个简单的订阅发布模式,不过从打印结果来看,有些尴尬,因为其实,小明只想订阅湖人,小李要订阅勇士。可是专栏都给他们推送了,显然不太合理。之所以出现这种情况是因为在执行on方法的时候将订阅函数列表中的函数依次都执行了。所以我们要对代码进行改造,我们可以先增加一个key,使订阅者只订阅自己感兴趣的消息。

let NBAcol={};//自定义一个NBA专栏对象
NBAcol.list={};// 这里放一个列表用来缓存订阅者的回调函数
NBAcol.on=function(key,fun){// 如果还没有订阅过此类消息,给该类消息创建一个缓存列表if(!this.list[key]){this.list[key]=[];}this.list[key].push(fun); //把fn先存到列表中
};
//发布事件
NBAcol.emit=function(){let key=Array.prototype.shift.call(arguments);// 取出消息类型名称let funs=this.list[key];//匹配对应的回调函数的结合if(!funs||funs.length===0){//如果没有订阅过消息,则return;return;};funs.forEach(fun => {fun.apply(this, arguments);});// 当发布的时候再把列表里存的函数依次执行
};
//小明的订阅NBA专栏
NBAcol.on('xiaomin',function(team){console.log("我订阅的球队是:"+team)
})
//小李的订阅NBA专栏
NBAcol.on('xiaoli',function(team){console.log("我订阅的球队是:"+team)
})
NBAcol.emit('xiaomin','湖人');
NBAcol.emit('xiaoli','勇士');
/*
我订阅的球队是:湖人;
我订阅的球队是:勇士;
*/
复制代码

这样子就可以啦,这个订阅发布的核心功能已经体现了。

如何取消事件的订阅

比如上面的列子,假如我们订阅了很多东西,不喜欢的时候我们要取消订阅,该怎么办呢?看如下代码:

 NBAcol.remove=function(key, fun) {// 这回我们加入了取消订阅的方法let funs = this.list[key];// 如果缓存列表中没有函数,返回falseif (!funs) return false;// 如果没有传对应函数的话// 就会将key值对应缓存列表中的函数都清空掉if (!fun) {funs && (funs.length = 0);} else {// 遍历缓存列表,看看传入的fun与哪个函数相同// 如果相同就直接从缓存列表中删掉即可funs.forEach((cb, i) => {if (cb === fun) {funs.splice(i, 1);}});}}// 取消dog方法的订阅NBAcol.remove('xiaoli',function(team){console.log("我订阅的球队是:"+team)});
复制代码

这样就可以取消订阅啦,但是实际的开源代码中,封装远比这要复杂,比如要考虑订阅数量,还有多模块订阅的封装等等,所以在这里我们还得在实际的业务模块中详细考虑。

发布订阅模式的缺点:

当然一个任何一个东西都是有两面性的,同样发布订阅模式存在以下问题:

1、创建订阅者需要消耗一定的时间和内存。

2、虽然可以弱化对象之间的联系,如果过度使用的话,反而使代码不好理解及代码不好维护等等。

转载于:https://juejin.im/post/5b2e65fee51d4558df370532

JavaScript中发布/订阅模式的理解相关推荐

  1. 用 JavaScript 实现发布/订阅模式

    重要申明:感谢原文作者--杠子,想看原文请戳这里!我转载了原文,修改了一些原文行文不通畅之处,并更改附上了自己的代码段,望请勿怪.挂在自己的博客下面一方面是为了收藏好文,方便自己温顾而知新:另一方面也 ...

  2. JavaScript的发布订阅模式

    这里要说明一下什么是发布-订阅模式. 发布-订阅模式里面包含了三个模块,发布者,订阅者和处理中心.这里处理中心相当于报刊办事大厅. 发布者相当与某个杂志负责人,他来中心这注册一个的杂志,而订阅者相当于 ...

  3. javascript 观察者(发布订阅)模式详解

    写给读者的话 本人是千千万万前端小白中的一员,所以对前端小白的痛苦感同身受,面对一个新的知识点,很多时候感到束手无策.网上搜资料,有的不全,有的看不懂,所以本人作为小白,很有义务将自己觉得理解了的知识 ...

  4. Javascript设计模式之发布-订阅模式

    简介 发布-订阅模式又叫做观察者模式,他定义了一种一对多的依赖关系,即当一个对象的状态发生改变的时候,所有依赖他的对象都会得到通知. 回忆曾经 作为一名前端开发人员,给DOM节点绑定事件可是再频繁不过 ...

  5. JavaScript设计模式 -发布订阅者模式

    1. 定义 发布订阅者模式又叫观察者模式,他定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得将得到通知 案例: 小明最近看上了一套房子,到了售楼处之后才被告知,该楼 ...

  6. 不好意思,观察者模式跟发布订阅模式就是不一样

    一.前言 一天,小猪佩奇去了一家西餐厅,点了一份西冷牛扒,还叫了圣女果.后来服务员上了一碟番茄:佩奇小姐,这是你的「圣女果」.佩奇猪一眼就看出了猫腻:这tm是番茄,不是圣女果啊!于是就跟服务员理论起来 ...

  7. 游戏服务器架构-设计模式之发布订阅模式

    发布订阅模式场景 熟悉消息中间件的同学应该对发布/订阅模式(Publish Subscribe Pattern)并不陌生.即使你不了解消息中间件,那么在平时生活中发布/订阅模式也是非常常见的场景. 比 ...

  8. Javascript中理解发布--订阅模式

    Javascript中理解发布--订阅模式 阅读目录 发布订阅模式介绍 如何实现发布--订阅模式? 发布---订阅模式的代码封装 如何取消订阅事件? 全局--发布订阅对象代码封装 理解模块间通信 回到 ...

  9. JavaScript 设计模式之发布-订阅模式(上)

    什么是发布订阅模式? 发布-订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知.在JavaScript开发中,我们一般用事件模型来替 ...

最新文章

  1. Python基础4_列表,元祖
  2. 推荐大家一个保护视力的Visual Studio皮肤
  3. 还在用代码苦苦调试大屏?用这个神器1小时搞定
  4. 21天Jenkins打卡Day12发布到测试服务器
  5. python二维数据读取对齐_[Python ] Python 多维数组转换的维度对齐问题
  6. dbscan聚类python_DBSCAN聚类算法 Python 代码
  7. 新手向python实现淘宝自动抢购
  8. 关于谷歌浏览器不能打开页面问题的解决
  9. FFT:快速傅里叶变换与高精度乘法
  10. GAN——生成对抗网络详解
  11. postgresql division by zero
  12. 判断多边形边界曲线顺/逆时针 两种方法
  13. Tikhonov正则化方法在测绘领域的综述
  14. ubuntu18与win10双系统引导修复
  15. win7-32位系统SqlServer2014版本下载与安装
  16. css样式的三种写法
  17. 极简风格的演讲型幻灯片设计
  18. 前端项目实战95-数组遍历继续处理
  19. 解析几何:第一章坐标系与坐标变换:平面直角坐标系、空间直角坐标系及其变换、极坐标系,圆柱面坐标系,球面坐标系
  20. chalk5.0.0不支持require()导入问题

热门文章

  1. JQuery中的类选择器
  2. k8s php mysql_在k8s上部署第一个php应用
  3. 设置一个DIV固定在底部,并且左右固定,垂直居中
  4. 推荐系统的封闭和禁锢问题
  5. 三维重建面试0:*SLAM滤波方法的串联综述
  6. 看看差距--完备技术面试
  7. java中类图概念,程序员眼中的UML(4)--类图释疑之一,Attribute和Property之区别
  8. AngularJS(6)-选择框Select
  9. java 电子商务云平台b2b b2c o2o springmvc+mybatis+spring cloud+spring boot
  10. iis 中后台调用exe文件