实现发布订阅模式

发布订阅模式(Pub/Sub )是前端和后端都非常常见的一种设计模式,本质是解耦:

  • 发布者(Publisher)发消息

  • 订阅者(Subscriber)接收消息

  • 中间通过一个"事件中心"来管理


🧠 一、核心思想

可以把它理解成:

"我不关心谁在听,只负责发;你不关心谁在发,只负责订阅。"

典型结构:

  • on:订阅事件

  • emit:发布事件

  • off:取消订阅


💻 二、手写一个发布订阅(JS实现)

这是最经典、面试也最常考的实现👇

复制代码
class EventBus {
  constructor() {
    this.events = {};
  }

  // 订阅
  on(eventName, callback) {
    if (!this.events[eventName]) {
      this.events[eventName] = [];
    }
    this.events[eventName].push(callback);
  }

  // 发布
  emit(eventName, ...args) {
    const handlers = this.events[eventName];
    if (handlers) {
      handlers.forEach(fn => fn(...args));
    }
  }

  // 取消订阅
  off(eventName, callback) {
    const handlers = this.events[eventName];
    if (!handlers) return;

    this.events[eventName] = handlers.filter(fn => fn !== callback);
  }

  // 只执行一次
  once(eventName, callback) {
    const fn = (...args) => {
      callback(...args);
      this.off(eventName, fn);
    };
    this.on(eventName, fn);
  }
}

🚀 三、使用示例

复制代码
const bus = new EventBus();

// 订阅
const handler = (msg) => {
  console.log('收到消息:', msg);
};

bus.on('test', handler);

// 发布
bus.emit('test', 'hello world');

// 取消订阅
bus.off('test', handler);

// 只执行一次
bus.once('onceEvent', (msg) => {
  console.log('只执行一次:', msg);
});

bus.emit('onceEvent', '第一次');
bus.emit('onceEvent', '第二次'); // 不会触发

⚔️ 四、和观察者模式的区别(面试重点)

很多人会混,这里帮你理清:

对比点 发布订阅 观察者模式
中间层 ✅ 有(EventBus) ❌ 没有
耦合度 低 高
关系 松散 直接依赖
使用场景 Vue事件、消息系统 响应式数据

👉 一句话总结:

发布订阅 = 多加了一层"中介",更解耦


🧩 五、前端实际应用场景

你项目里其实已经可能用过👇

1️⃣ Vue / React 事件通信

复制代码
// mitt / eventemitter3 本质就是 pub/sub

2️⃣ 跨组件通信(非父子)

  • EventBus

  • 全局状态管理(Redux 本质也有类似思想)

3️⃣ WebSocket 消息分发

复制代码
socket.onmessage = (msg) => {
  eventBus.emit(msg.type, msg.data);
};

4️⃣ 你之前做的性能平台(很适合用)

比如:

  • 图表联动(ECharts)

  • 筛选条件同步

  • 多模块刷新


🔥 六、进阶优化(高级面试点)

你可以再升级一下👇

✅ 1. 支持事件命名空间

复制代码
"user:login"
"user:logout"

✅ 2. 支持通配符

复制代码
"user:*"

✅ 3. 异步发布(Promise)

复制代码
emit async

✅ 4. 防止重复订阅

复制代码
Set 替代 Array

🧭 七、一句话总结

发布订阅模式 = "事件中心 + 松耦合通信",是大型前端架构必备能力

相关推荐
子兮曰3 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰3 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万3 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝3 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋3 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁3 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
李少兄3 天前
JavaScript 隐式全局变量解析
javascript
汉堡大王95273 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大3 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师3 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端