持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情
前情提要
对于发布订阅模式可能大家是听得很多,偶有能用到的。但是对于真实的发布订阅模式可能并不是特别的清晰。其实在我们的现实生活中就有很多发布订阅的案例。
现实中的案例
- 比如以前小区的报纸订阅,你在邮局办了一项业务,每天给你指定的位置送一份当天的报纸。当最新的报纸来了之后邮局会派专门的送报人员按时按点每天去给你送报。
- 还有就是新鲜牛奶,有公司提供送早餐奶的服务,你去购买这项服务,每天早上送奶公司会把热腾腾的鲜牛奶送到指定的地方。这里面就是用到了典型的发布订阅模式。你去订阅某项服务,然后服务提供商在服务更新的时候对你进行更新。
- 上面的两个例子可能对于九五后,零零后不是特别的感同身受,毕竟信息电子化时代,早已没了送报纸这项目服务,便捷的早餐店导致也没了早餐奶的配送服务。但是相信外卖这个例子你一定很熟悉。你在平台上下了个订单,买了哪份饭。然后平台通知商家配餐,最后由骑手配送。
那么如何把这种模式在代码中实现呢?
- 发布订阅模式一共有是三个角色,一个是发布者,一个是订阅者,一个是中间经纪人。
- 其中发布者告诉中间经纪人它要发布一个事件,已经实际内容。然后中间经纪人去查看有没有人订阅了这个事件,如果有那就主动告诉那些订阅者,该事件被触发,然后把实际内容传给订阅者。
- 先实现一个简易版的发布订阅
const agent = {}; // 创建发布方法 function publish() { const eventName = arguments[0] if (agent.hasOwnProperty(eventName)){ for (let key of agent[eventName]) { key(...arguments) } } else { agent[eventName] = [] } } // 创建订阅方法 function subscriber(eventName, fn) { if (!agent.hasOwnProperty(eventName)) agent[eventName] = [] agent[eventName].push(fn) } // 声明订阅后如果发布方发布了该事件所需要执行的回调函数 const realSubscriber = function (...arg) { console.log(...arg) } subscriber('test', realSubscriber) publish('test', 'success') // test success - 至此一个简易版的发布订阅就搞定了。
- 现在将其封装成一个类
class model { constructor(obj) { this.agent = obj; } publish() { const eventName = arguments[0] if (this.agent.hasOwnProperty(eventName)){ for (let key of this.agent[eventName]) { key.apply(this, arguments) } } else { this.agent[eventName] = [] } } subscriber(eventName, fn) { if (!this.agent.hasOwnProperty(eventName)) this.agent[eventName] = [] this.agent[eventName].push(fn) } } const newAgent = new model({}) newAgent.subscriber('test', function() { console.log(...arguments) }) newAgent.publish('test', 'success') // test success
总结
在实际中有很多人会把发布订阅模式与发布者模式弄混淆了。都以为他们是同一种模式,其实两者概念看似有些相似,但是实际商量着还是有着本质的区别。下一篇文章会讲解两者的区别,敬请关注。