深色模式
发布订阅模式
发布订阅模式在前端开发中非常常见。前端有很多异步场景,比如按钮点击事件,消息广播等都有应用。
发布订阅消息
假如我们要实现一个发布订阅平台消息的操作,我们该如何做呢 ?
js
function Notice() {}
Notice.clientList = {};
Notice.subscribe = function (key, fn) {
if (!this.clientList[key]) this.clientList[key] = [];
let fnIndex = this.clientList[key].indexOf(fn);
if (fnIndex === -1) {
this.clientList[key].push(fn);
}
};
Notice.publish = function (...args) {
let key = args.shift();
if (!key || !this.clientList[key]) return;
this.clientList[key].forEach(fn => {
fn.apply(this, args);
});
};
Notice.remove = function (key, fn) {
var fns = this.clientList[key];
if (!fns) return;
// 移除所有订阅
if (!fn) {
fns.length = 0;
return;
}
let fnIndex = fns.findIndex(item => item === fn);
if (fnIndex > -1) fns.splice(fnIndex, 1);
};
// 订阅者
Notice.subscribe('computer', (...args) => console.log('computer subfn1', args));
Notice.subscribe('computer', (...args) => console.log('computer subfn2', args));
Notice.subscribe('science', (...args) => console.log('science subfn3', args));
// 消息发布者
Notice.publish('computer', 'js', 'css');
setTimeout(() => {
Notice.publish('science', 'math');
}, 2000);
上面的代码中可以看到,消息订阅者需要先发起订阅请求,等待消息发布者发布消息,才能接收到通知。那么能不能没有订阅者的时候,也能发布消息,等到出现订阅者的时候,将消息传给订阅者呢?
js
Notice.subscribe = function (key, fn) {
// 如果有缓存的订阅消息,则接收
if (this.msgCache[key]) {
this.msgCache[key].forEach(args => {
fn.apply(this, args);
});
}
if (!this.clientList[key]) this.clientList[key] = [];
let fnIndex = this.clientList[key].indexOf(fn);
if (fnIndex === -1) {
this.clientList[key].push(fn);
}
};
Notice.publish = function (...args) {
let key = args.shift();
if (!key) return;
// 没有订阅消息,缓存当前消息
if (!this.clientList[key]) {
if (!this.msgCache[key]) this.msgCache[key] = [];
this.msgCache[key].push([...args]);
return;
}
this.clientList[key].forEach(fn => {
fn.apply(this, args);
});
};
// 消息发布者
Notice.publish('computer', 'js', 'css');
setTimeout(() => {
Notice.publish('science', 'math');
}, 2000);
// 订阅者
Notice.subscribe('computer', (...args) => console.log('computer subfn1', args));
Notice.subscribe('computer', (...args) => console.log('computer subfn2', args));
Notice.subscribe('science', (...args) => console.log('science subfn3', args));