引子
你被小区群聊"骚扰"过吗? 某天凌晨5点,我被手机震醒------小区广场舞群又炸了: "张姐,今天音响音量调小点呗?" "李哥,占位的红布帮我挪挪,我带孙女晚点到" "王姨,新舞教学视频发群里了啊"
放下手机我突然顿悟:这不就是活生生的发布订阅模式吗!群主是事件中心,跳舞的是订阅者,发消息的是发布者... 前端er天天挂在嘴边的设计模式,原来早就渗透到生活里了。
什么是发布订阅?说白了就是"中间商赚差价"
先看个灵魂比喻:
- 你关注了"稀土掘金"公众号(订阅事件)
- 掘金小编发了篇干货文(发布事件)
- 你收到推送并点开(执行回调)
这里的公众号平台 就是关键------它让订阅者和发布者互不认识,却能精准通信。这就是发布订阅的核心:通过第三方(事件中心)实现一对多通信
反观隔壁"观察者模式"就很耿直:发布者直接抱着订阅者的微信猛发消息(直接通信),想想都觉得窒息...
手把手实现一个"群聊管理器"(EventEmitter)
我们用代码还原小区群聊的功能,先搭个基础框架:
js
class EventEmitter {
constructor() {
this.eventList = {}; // 存储事件列表,比如 { '广场舞通知': [张姐, 李哥]
}
}
1. 先实现"入群"功能(on方法)、、
想接收消息,得先入群吧?on
方法就是干这个的:
js
on(eventName, cb) {
if (!this.eventList[eventName]) {
this.eventList[eventName] = []; // 没这个群就新建一个
}
this.eventList[eventName].push(cb); // 拉人入群
}
比如张姐要听广场舞通知:
js
eventEmitter.on('广场舞通知', () => console.log('张姐收到,马上到'));
2. 再搞"发通知"功能(emit方法)
群主发通知,群里所有人都能收到:
js
emit(eventName) {
if (this.eventList[eventName]) {
const handlers = this.eventList[eventName].slice(); // 复制一份避免发消息时有人退群
handlers.forEach(cb => cb()); // 挨个通知
}
}
群主喊话:
js
eventEmitter.emit('广场舞通知'); // 输出:张姐收到,马上到
3. "退群"功能也得有(off方法)
总有人想清静几天,off
方法安排上:
js
off(eventName, cb) {
const callbacks = this.eventList[eventName];
const index = callbacks.indexOf(cb);
if (index !== -1) {
callbacks.splice(index, 1); // 把人移出群
}
}
4. 特殊需求:"只看一次"(once方法)
王姨只想看一次新舞教学,之后就退群:
js
once(eventName, cb) {
const wrap = () => {
cb(); // 先执行回调
this.off(eventName, wrap); // 看完就退群
};
this.on(eventName, wrap);
}
这波操作,堪称代码界的"阅后即焚"!
实战:用发布订阅解决"异步依赖"问题
比如有个场景:
- fnA要等1秒后执行,完事通知大家
- fnB订阅这个通知,收到后执行
用我们的EventEmitter轻松搞定:
js
const eventEmitter = new EventEmitter();
// fnA:1秒后发布"next"事件
function fnA() {
setTimeout(() => {
console.log('fnA 执行了');
eventEmitter.emit('next'); // 通知大家
}, 1000);
}
// fnB:订阅"next"事件
function fnB() {
setTimeout(() => {
console.log('fnB 执行了');
}, 500);
}
eventEmitter.on('next', fnB);
fnA(); // 1秒后输出"fnA 执行了",接着输出"fnB 执行了"
没有回调地狱,代码清爽得像刚洗过澡~
总结:这模式到底香在哪?
- 解耦神器:发布者和订阅者互不关心对方是谁,只管发和收
- 灵活扩展:想加新功能?直接加个订阅者就行,不用改老代码
- 异步友好:处理各种异步操作(比如接口请求、定时器)时特别顺手
现在再看小区群聊,是不是觉得程序员的世界和现实无缝衔接了?下次被群消息烦的时候,不妨默念:"这是发布订阅模式,我懂!"------瞬间就高大上起来了有没有~ 最后