JavaScript-发布订阅模式

什么是发布订阅模式

  • 关注了一个视频博主,这就是一个订阅过程。

  • 视频博主更新了视频,所有关注了博主的人都会收到提醒,这就是一个发布过程。

优点

  • 解耦合:关注者想第一时间收到视频只要关注(订阅)即可。博主只需要关注更新(发布)视频这一个动作即可。

巨极简版的发布订阅模式!!!

内容不完全,帮助大家快速对发布订阅模式有一个大致的认识

js 复制代码
// publish 发布
// subscribe 订阅
// PubSub看作是调度中心
const PubSub = {
    list: [],
    // 发布方法
    publish() {
        this.list.forEach(item => item())
    },
    // 订阅方法
    subscribe(callback) {
        this.list.push(callback)
    }
}

// 定义两个回调函数 表示订阅者
function demo1() {
    console.log('demo1');
}

function demo2() {
    console.log('demo2');
}

// 现在进行订阅操作
PubSub.subscribe(demo1)
PubSub.subscribe(demo2)

// 现在开始发布
PubSub.publish()

运行结果:

js 复制代码
demo1
demo2
  • 上述代码存在一个问题:无法实现事件的细分

也就是说,无法实现一个用户名为a的用户的订阅,也不能实现一个事件b的发布。

上述的代码在发布的时候,直接一股脑从头把事件遍历到尾了。

极简代码的改进

那么怎么解决按类来进行事件的订阅和发布呢?

设想一下:现在有个用户a,需要订阅一件事情b。有一个用户c需要订阅事件de

那么list的数组结构其实可以用对象形式来做替代:一个名为a的对象存在存储了属性b。一个名为c的对象存储了一个属性de

自然而然地,那进行订阅操作的时候,就需要传入两个参数了,你需要告诉调度中心,你的名字是啥,然后传入一个回调函数告诉调度中心当事件发布的时候调度中心需要做什么

那么发布的时候,自然也可以加一个参数,来表示我们要发布的是哪一个用户所订阅的内容。

改进后的代码如下:

js 复制代码
const PubSub = {
    // 换成对象
    message: {},
    // 发布方法
    publish(type) {
        if (!this.message[type]) {
            return
        }

        this.message[type].forEach(item => item())
    },
    // 订阅方法
    subscribe(type, callback) {
        // 判断type是否存在
        if (!this.message.type) {
            this.message[type] = [callback]
        } else {
            this.message[type].push(callback)
        }
    }
}

function demoA() {
    console.log('demoA');
}

function demoB() {
    console.log('demoB');
}

PubSub.subscribe('A', demoA)
PubSub.subscribe('B', demoB)

// 发布操作
PubSub.publish('A')
PubSub.publish('B')

运行结果:

js 复制代码
demoA
demoB

上述代码就实现了根据每一个用户订阅的事件进行专门地发布

增加取消订阅功能

能订阅、能发布,下面再添加一个取消订阅的功能。 注意:取消订阅的时候,需要指定取消订阅的那个用户名,不然调度中心是不知道你要取消订阅哪一个用户的。

js 复制代码
const PubSub = {
    message: {},
    publish(type) {
        if (!this.message[type]) {
            return
        }
        this.message[type].forEach(item => item())
    },
    subscribe(type, callback) {
        if (!this.message.type) {
            this.message[type] = [callback]
        } else {
            this.message[type].push(callback)
        }
    },
    // 添加取消订阅的方法
    // 注意 需要指定 type 以及对应的事件:callback
    unsubscribe(type, callback) {
        // 如果不存在该类型 直接返回
        if (!this.message[type]) {
            return
        } else {
            this.message[type] = this.message[type].filter(item => item != callback)
        }

    }
}

function demoA() {
    console.log('demoA');
}

function demoB() {
    console.log('demoB');
}

PubSub.subscribe('A', demoA)
PubSub.subscribe('B', demoB)

PubSub.publish('A')
PubSub.publish('B')

// 进行取消订阅
PubSub.unsubscribe('A', demoA)

console.log('我是华丽的分割线');

PubSub.publish('A')
PubSub.publish('B')

运行结果:

js 复制代码
emoA
demoB
我是华丽的分割线
demoB

总结

发布订阅模式中存在三个角色:订阅者发布者调度中心

订阅者只负责订阅消息,发布者只负责发布消息。实现了业务之间的解耦。发布者负责总体的调度。

最后

这个模式使用的场景太多了,vue的事件绑定就有使用到该设计模式。我所在的公司也有一个项目是基于发布订阅模式的。

ps:本人正在学习写博客,如果写的不好还请见谅!!可以的话也可以提提建议我好改进!!大家一起进步啊😁

相关推荐
Web打印1 分钟前
HttpPrinter是一款基于HTTP协议的跨平台Web打印解决方案,
javascript·php
少油少盐不要辣7 分钟前
前端如何处理AI模型返回的流数据
前端·javascript·人工智能
跟着珅聪学java10 分钟前
以下是使用JavaScript动态拼接数组内容到HTML的多种方法及示例:
开发语言·前端·javascript
巴拉巴拉~~18 分钟前
KMP 算法通用图表组件:KmpChartWidget 多维度可视化 + PMT 表渲染 + 性能对比
前端·javascript·microsoft
智算菩萨24 分钟前
基于spaCy的英文自然语言处理系统:低频词提取与高级文本分析
前端·javascript·easyui
刘一说34 分钟前
Vue单页应用(SPA)开发全解析:从原理到最佳实践
前端·javascript·vue.js
疯狂成瘾者35 分钟前
前端vue核心知识点
前端·javascript·vue.js
hh随便起个名9 小时前
力扣二叉树的三种遍历
javascript·数据结构·算法·leetcode
我是小路路呀9 小时前
element级联选择器:已选中一个二级节点,随后又点击了一个一级节点(仅浏览,未确认选择),此时下拉框失去焦点并关闭
javascript·vue.js·elementui
敲敲了个代码10 小时前
隐式类型转换:哈基米 == 猫 ? true :false
开发语言·前端·javascript·学习·面试·web