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需要订阅事件d和e。

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

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

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

改进后的代码如下:

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

相关推荐
u01110267524 分钟前
JPG、PNG、WebP 怎么选?按透明度、体积和使用场景做判断
前端·javascript·vue.js·图像处理·ai作画
hhb_6182 小时前
一键生成数据看板,ECharts实战演示
前端·javascript·echarts
const_qiu3 小时前
第一章 1.1-1.2:基础模型调用与 TypeScript 入门 —— Java 开发者的视角
java·javascript·typescript
衍辉channel7 小时前
衍辉AI速递 10.14|谷歌发布Gemini 4 Argon模型等9条AI资讯
javascript
vipxieliang7 小时前
JavaScript 事件循环与任务队列:从 setTimeout 到 Promise
前端·javascript
Misnearch8 小时前
React中的回调
前端·javascript·react.js
Eider199810 小时前
大模型输出格式幻觉解决思路
开发语言·前端·javascript
志尊宝10 小时前
Vue3 零基础每日笔记(085):项目上线前 Checklist——环境变量、报错监控、安全自查
前端·javascript·笔记·安全·信息可视化·echarts
志尊宝10 小时前
Vue3 零基础每日笔记(088·完结):从零到一——一个完整 Vue3 项目的成长复盘
前端·javascript·vue.js·笔记·ecmascript·#vue.js
传人once10 小时前
企业官网静态页基础结构如何搭
javascript·css