js手写发布订阅(pubsub)

js手写发布订阅(pubsub)

面了一个央企,一上来就让我手写pubsub,没写出来,今天梳理和学习一下怎么写。

发布订阅模式:包含发布者(publisher),订阅者(subscriber),消息中心(message center)。

发布者发布消息给消息中心,并且可以携带参数。

订阅者向消息中心订阅消息,并且可以获取发布者发送的参数。

消息中心在获取到发布者的消息后通知订阅者并且转发参数。

消息中心

消息中心具有的功能是:消息中心类被实例化后可以接受publish新消息进去,也可以接受subscribe消息,如果消息中心收到了新的publish的消息是有人订阅的则通知订阅者。

消息中心本身可以以消息类型和消息内容的方式存储消息。

消息中心还可以以订阅者和订阅的消息类型的方式存储用户的订阅。

MessageCenter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class MessageCenter {
constructor() {
// 消息集合:存放形式是消息类型(消息名称)和消息内容的键值对
this.messages = {};
// 监听集合:存放形式是订阅者和订阅消息类型的键值对
this.listeners = {};
}

// publish方法:在消息中心中添加发布者的消息,参数是消息类型和消息内容
publish(type, content) {
if (!this.messages.hasOwnProperty(type)) {
this.messages[type] = [];
}
this.messages[type].push(content);
}

// subscribe方法:在消息中心中添加订阅者订阅的内容
subscribe(type, callback) {
if (!this.listeners.hasOwnProperty(type)) {
this.listeners[type] = [];
}
this.listeners[type].push(callback);
}

// notify方法:通知订阅者
notify(type) {
const contents = this.messages[type];
const subscribers = this.listeners[type] || [];
subscribers.forEach((callback, index) => callback(contents[index]));
}
}

发布者

Publisher
1
2
3
4
5
6
7
8
9
10
11
class Publisher {
// context是MessageCenter实例
constructor(name, context) {
this.name = name;
this.context = context;
}

publish(type, content) {
this.context.publish(type, content);
}
}

订阅者

Subscriber
1
2
3
4
5
6
7
8
9
10
11
class Subscriber {
// context是MessageCenter实例
constructor(name, context) {
this.name = name;
this.context = context;
}

subscribe(type, callback) {
this.context.subscribe(type, callback);
}
}

评论