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

相关推荐
游九尘1 小时前
JavaScript 实现三段式版本号对比函数(app升级用)
javascript·uni-app
zhiSiBuYu05171 小时前
Claude-Code 新手极速上手指南
javascript·node.js
罗超驿2 小时前
18.Web API 实战:元素与表单属性的获取和修改
开发语言·前端·javascript
山河已无恙2 小时前
BPF-eBPF 开发路线二:libbpf、CO-RE 与 libbpf-bootstrap认知
javascript·bootstrap·php
ZengLiangYi3 小时前
React Query + REST API 最佳实践
javascript·后端·react.js
ZengLiangYi3 小时前
Fastify 加 Electron:把 Web 服务嵌进桌面应用
前端·javascript·后端
胡萝卜术4 小时前
从零搭建生成式AI项目:OpenAI + Node.js 环境配置与密钥安全实践
前端·javascript·面试
柒和远方4 小时前
每日一学V012: 从 Python 到 Node.js:一个 AI Native 开发者的 JavaScript 调用 LLM 实战
javascript·node.js·api
STDD4 小时前
Farming Simulator 25(模拟农场 25) Linux 专服搭建完全指南
linux·运维·javascript
超人气王4 小时前
新手学前端 JavaScript 类型判断:一篇彻底搞懂 typeof、instanceof 和 Object.prototype.toString
前端·javascript