发布订阅模式与简单的 JS 实现

发布订阅模式与简单的 JS 实现

本文写于 2020 年 9 月 22 日

观察者模式(Observer Pattern)是一种设计模式,也可以叫做「发布-订阅模式」。

等等,其实我也不清楚,通常你在网上会看到上面这一段话,但我在 Angular 文档中读到谷歌的说法是这样的:观察者模式和发布/订阅模式非常相似(但不完全一样)。

好吧,我们姑且就直说发布订阅模式吧。

发布订阅模式就像你订了一本杂志,每当杂志新刊发布的时候,所有订阅过杂志的人都会收到新刊一样。

观察者模式定义了对象之间一种 一对多 的依赖关系,每当该对象的状态发生改变的时候,所依赖于它的其他对象都将得到通知。

在 JavaScript 中,我们会经常接触到一个很类似的东西——事件。

事件与观察者模式

我们先为一个 #app 元素添加两个点击事件:

document.querySelector('#app').addEventListener('click', () => {
// 事件 1
});
document.querySelector('#app').addEventListener('click', () => {
// 事件 2
});

这个时候,我们点击 #app 元素或者使用 document.querySelector('#app').click() 或者 document.querySelector('#app').dispatchEvent('click') 来触发时,这两个事件都会被触发——是不是类似与很多对象依赖于一个对象,该对象改变后所有依赖者都会被触发。

自定义「发布-订阅」

我们来自定义一个事件来试试。

首先我们需要一个数组储存所有的触发函数,这样我们就可以对其进行遍历,后触发每一个事件。

const children = [];

我们还需要一个方法,来对 children 数组进行 push

const listen = (fn) => {
children.push(fn);
}

我们再增加一个触发函数 trigger,让它去遍历并触发我们的 children

const trigger = () => {
children.forEach((child) => {
child();
})
}

OK,接下来我们整合一下:

class eventHub {
children = {}
listen(key, fn) {
if(this.children[key]) {
this.children[key].push(fn);
} else {
this.children[key] = [fn]
}
}
trigger(key) {
this.children[key]?.forEach((child) => {
child();
});
}
remove(key, fn) {
if(this.children[key]) {
const children =this.children[key]
const target = children.indexOf(fn)
this.children[key] = [...children.slice(0, target), ...children.slice(target + 1)]
}
}
}

这里我们将数组换成了对象,并且为函数增加了参数,因为我们希望够可以对多个事件进行监听。

还添加了一个移除事件——所以我们最好使用具名函数,如果是匿名函数就无法移除监听了!

有哪些例子?

例如一个电商网站的登陆系统,需要获取用户基础信息后,获取用户的各项历史记录:

function onLogin() {
getUserInfo()
.then(() => {
return getUserHistory()
})
.then(() => {
getUserXXX()
})
}

那么一旦我们需要新增一个功能,就需要在这个长函数中增加新项。

如果使用了发布-订阅模式,就可以非常简单的写上新的、独立的事件监听了。

(完)

posted @   徐航宇  阅读(710)  评论(0编辑  收藏  举报
编辑推荐:
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
阅读排行:
· 本地部署 DeepSeek:小白也能轻松搞定!
· 如何给本地部署的DeepSeek投喂数据,让他更懂你
· 从 Windows Forms 到微服务的经验教训
· 李飞飞的50美金比肩DeepSeek把CEO忽悠瘸了,倒霉的却是程序员
· 超详细,DeepSeek 接入PyCharm实现AI编程!(支持本地部署DeepSeek及官方Dee
点击右上角即可分享
微信分享提示