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

相关推荐
昨天;明天。今天。29 分钟前
案例-博客页面简单实现
前端·javascript·css
萧鼎34 分钟前
JavaScript可视化
javascript
安冬的码畜日常1 小时前
【玩转 JS 函数式编程_008】3.1.2 JavaScript 函数式编程筑基之:箭头函数——一种更流行的写法
开发语言·javascript·ecmascript·es6·this·箭头函数
小爱丨同学1 小时前
宏队列和微队列
前端·javascript
沉登c2 小时前
Javascript客户端时间与服务器时间
服务器·javascript
持久的棒棒君2 小时前
ElementUI 2.x 输入框回车后在调用接口进行远程搜索功能
前端·javascript·elementui
小程xy5 小时前
react 知识点汇总(非常全面)
前端·javascript·react.js
非著名架构师6 小时前
js混淆的方式方法
开发语言·javascript·ecmascript
多多米10057 小时前
初学Vue(2)
前端·javascript·vue.js
敏编程7 小时前
网页前端开发之Javascript入门篇(5/9):函数
开发语言·javascript