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

相关推荐
芜青3 小时前
JavaScript手录18-ajax:异步请求与项目上线部署
开发语言·javascript·ajax
织_网3 小时前
Electron 核心 API 全解析:从基础到实战场景
前端·javascript·electron
2401_837088504 小时前
setup 语法糖核心要点
开发语言·前端·javascript
你也向往长安城吗5 小时前
基于 navmesh 的路径搜索技术剖析 (游戏、三维方向必看!!!)
javascript·游戏·游戏开发
JustHappy6 小时前
「Versakit攻略」🔥Pnpm+Monorepo+Changesets搭建通用组件库项目和发包流程
前端·javascript·vue.js
long3166 小时前
适配器模式 java demo
java·javascript·后端·程序人生·设计模式·适配器模式
2401_837088507 小时前
ref 简单讲解
前端·javascript·vue.js
汪子熙8 小时前
Vite 极速时代的构建范式
前端·javascript
叶常落8 小时前
[react] js容易混淆的两种导出方式2025-08-22
javascript
摸着石头过河的石头10 小时前
大模型时代的前端开发新趋势
前端·javascript·ai编程