当前位置: 首页 > 后端技术 > Node.js

本文带你了解发布-订阅和观察者模式

时间:2023-04-03 21:04:06 Node.js

发布-订阅发布-订阅是极其基础和重要的设计模式之一,如果你想在面试中考察一个设计模式,我想我会选择发布-毫不犹豫地订阅。那么到底什么是发布订阅,适用于哪些场景呢?刚开始学习这个模型的时候,我也是一头雾水。大佬们跟我说前端的事件绑定就是一个发布订阅(黑色问号脸)。是的,这确实是,这句话是不是总结了发布和订阅?深入学习和理解发布订阅并不容易,但也不难。人们常说,一本书读一百遍,就会明白其中的含义。很多事情只是时间问题。用多了自然就来了。下面我结合我的学习过程,说说我对发布-订阅模型的理解。写一个简单的publish-subscribepublish-subscribe当然分为订阅和发布两部分,就像关注的公众号一样,只有订阅了才会收到他的发布。订阅和发布总要有一个载体,或者说一个目标。以公众号的订阅发布为例,那么载体应该是公众号,比如我的公众号网富就是??一个载体,所有的订阅者应该都存放在公众号的某个地方。请关注我的公众号:网富,发1024获取更多前端学习资源:申报载体,将所有订阅者放入该载体。//声明一个公众号作为运营商类Account{constructor(name){//这里的名字没有特殊意义,我的本意是指代当前新的公众号namethis.name=name//所有订阅所有的订阅者都放在this的subscribers属性上公众号this.subscribers={}}}运营商已经存在,接下来就是在调度中心classAccount中添加订阅的过程{//订阅过程,名称为订阅者的账号,fn代表订阅的事件//订阅者可能会订阅多个事件,所以将事件作为一个数组//考虑到重复订阅的可能性,set也可以作为订阅事件的容器subscribe(name,fn){if(typeoffn!=='function')returnconstsubscribers=this.subscribersif(subscribers[name]){//deduplication!subscribers[name].includes(fn)&&subscribers[name].push(fn)}else{subscribers[name]=[fn]}}}接下来是发布流程classAccount{//发布流程可能只针对部分订阅者,比如某个用户发了一条消息//那么公众号只针对Reply,所以这里只发布给某个订阅者publish(name){constsubscribers=this.subscribersif(subscribers[name]){subscribers[name].forEach(fn=>fn())}}}至整个订阅发布完成。目前我们已经实现了最基本的订阅和发布功能。比如张三订阅了我的公众号,执行过程如下:constwebRuichi=newAccount('webRuichi')//张三订阅webRuichi.subscribe('张三',function(){console.log(`张三订阅了公众号`)})//公众号发布内容给张三webRuichi.publish('张三')//输出-->张三订阅了公众号所以至此,我们的订阅发布已经可以运行了,但是还存在一些不足。比如张三在订阅内容的时候需要一些特殊的信息。当公众号发布张三的信息时,把你需要的东西发给他。接下来,对发布过程进行修改:..rest))}}}接下来张三订阅的时候,可以告诉公众他需要什么样的信息://张三订阅的时候,他想知道自己订阅的是哪个公众号。webRuichi.subscribe('张三',function(name){console.log(`张三订阅了"${name}"公众号`)})//公众号告诉张三自己的公众号发布时的名字webRuichi.publish('张三',webRuichi.name)//输出-->张三已经订阅了“webRuichi”公众号订阅发布的实现很简单,就是把订阅者的事件放到在自己的数组中,在发布的时候,获取对应的订阅者,依次执行事件。应用于web前端领域,最常见的就是事件绑定。初始化时为某个按钮订阅相关事件(这里以点击事件为例),触发点击时释放。这个按钮是一个承载事件的载体,事件由订阅者订阅,并在点击事件触发时发布。大家应该都清楚,订阅发布是用来解耦的。作为一个初学者,为什么他与订阅和发布脱钩?这不是函数数组的顺序执行,解耦了吗?还有,他真正的潜力在哪里?带着这些问题继续探索。在哪里使用发布和订阅?Vue组件传参相信大家在面试中都遇到过Vue中组件间传参的问题。当组件嵌套太深时,普通的props传参会很麻烦,比如组件A要给表弟B组件传参,路径会是这样:A组件—>父组件—>爷爷组件—>叔叔组件—>B组份,前后会经过三个组份,这会对三层组份造成污染,也会给后期维护带来很多麻烦。这时候以发布订阅的方式传递参数就会非常方便。我们看一下代码://main.js文件importVuefrom'vue'importEventfrom'./event'//引入订阅并发布Vue.prototype.$event=newEvent()//一个组件//Bcomponent