simker

Life is too short, just make it.


  • 首页

  • 归档

  • 分类

  • 标签

  • 关于

  • 音乐

  • 搜索

订阅发布设计模式

发表于 2021-03-19 更新于 2021-09-29 分类于 JavaScript 阅读次数: Disqus:
本文字数: 2.1k 阅读时长 ≈ 2 分钟

Your browser does not support the audio tag.

最近在看react 的时候发现比较有意思的事情。

react 的组件通信是一个比较常见的问题,大致分为以下几种:

  • 父->子通信:传入 props 解决
  • 子->父通信:父组件传入一个函数给子组件,通过子组件调用触发,拿到值;或者用 HOC
  • 跨越层级比较多的通信:通过 Context 传值
  • 兄弟之间的通信:
    • 放在一个父节点下,通过 props 传值,或者函数传值
    • 哥俩都通过 HOC 包装起来传值
    • 直接用 Context 传值
    • 把数据放在第三方(或者全局,比如 Redux),统一通过第三方来获取数据
    • 通过发布订阅的方式传值,本篇主要记这个。

发布订阅设计模式一般分为三个部分:

  • 发布者:就是喊话的人(一般就几个人,比较少)
  • 订阅者:就是听者(可能一两个,可能很多人)
  • 通道:就是传声渠道(比如空气,电话)

这个模式在生活中也比较常见:

  • 在油管上订阅自己喜欢的 Youtuber,看 Youtuber 发布的视频。
  • 以前家里人都喜欢看湖南卫视,到了黄金时间都锁定湖南卫视看热播剧场。
  • 推特关注自己喜欢的偶像、体育赛事,新闻时事,有信息第一时间知道。

其中,上述的关注对象一般是发布者,关注人一般是订阅者,其中的”油管“,”湖南卫视“,”推特“一般是渠道。了解了大致的原理,我们可以手写一个发布订阅的小玩意加深印象。

首先,我们需要一个对象来存储订阅关系,并且需要这是一个单列的,因为不能简单的让外部进行改动。

1
2
3
class SubPub {
private static messages: Object = {};
}

然后,实现我们的订阅功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
static subscribe(message: string, fn: Function) {
if (!Object.prototype.hasOwnProperty.call(this.messages, message)) {
// @ts-ignore
this.messages[message] = {};
}

const uid = ++this.lastUid; // 小知识,为什么不用 this.lastUid++ ?

// @ts-ignore
this.messages[message][uid] = fn;

return uid;
}

上面我们为了更方便操作函数,给函数加上了唯一索引,所以我们需要在类的定义里加上索引定义,同样也是单列。

1
private static lastUid: number = 0;

上面已经实现了订阅了,我们来实现发布功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
static publish(message: string, data?: any) {
if (!Object.prototype.hasOwnProperty.call(this.messages, message)) {
return;
}

// @ts-ignore
for (const uid in this.messages[message]) {
// @ts-ignore
const fn = this.messages[message][uid];

fn(data);
}
}

现在我们就可以去使用了。

1
2
3
4
5
6
let myUid = NaN;
const myLuckyNumber = (number) => {
console.log("my lucky number : ", number);
}
myUid = SubPubC.subscribe("lucky", myLuckyNumber); // 订阅
SubPub.publish("lucky", Math.round(Math.random() * 10)); // 发布

有了订阅,应该也有取消的功能,因为很多业务是只能登陆用户才能办理的,或者说业务有时效性的。
下面我们来实现取消的功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
static unsubscribe(message: string, uid: number) {
if (!Object.prototype.hasOwnProperty.call(this.messages, message)) {
return;
}

// @ts-ignore
if (!Object.prototype.hasOwnProperty.call(this.messages[message], uid)) {
return;
}

// @ts-ignore
delete this.messages[message][uid];
}

用起来也很方便。

1
SubPub.unsubscribe("lucky", myUid);

不方便的地方就是存储唯一索引麻烦些。

好了,本篇的大致内容差不多就是这些了,以上只是简单的书写,我们只要了解核心原理就行了,如果你想要看更深入的话,访问PubSubJS的github。

enjoy and happy coding!

Cai xian 微信支付

微信支付

Cai xian 支付宝

支付宝

# react # subpub
sql语句之query笔记
前端面试题整理之CSS篇
Cai xian

Cai xian

A super nice guy!
24 日志
12 分类
15 标签
© 2019 – 2021 Cai xian | 70k | 1:04
由 Hexo 强力驱动 v3.9.0
|
主题 – NexT.Pisces v7.3.0
|