浅谈发布——订阅模式

发布订阅模式可以说是前端必须要熟悉的一种模式,在工作和面试中都会经常遇到,今天就来简单聊聊发布订阅模式。

什么是发布订阅模式

在软件架构中,发布/订阅 (Publish--subscribe pattern)是一种消息范式,消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者)。而是将发布的消息分为不同的类别,无需了解哪些订阅者(如果有的话)可能存在。同样的,订阅者可以表达对一个或多个类别的兴趣,只接收感兴趣的消息,无需了解哪些发布者(如果有的话)存在。

实现一个简单的发布订阅模式

一个简易的发布订阅模式应该有以下能力:

  • 一个调度中心
  • 添加订阅、移除订阅
  • 触发事件、只触发一次事件

第一步:实现一个调度中心

我们希望调度中心具有这样的一个结构,整体是对象,key 是 string,代表事件名,value 是一个 array,代表事件名对应的多个事件。所以我用 Class 类来实现。

javascript 复制代码
class EventEmitter {
  constructor() {
    this.events = {}
  }
}

第二步:实现添加订阅、移除订阅功能

javascript 复制代码
class EventEmitter {
  constructor() {
    this.events = {}
  }
  // 添加订阅
  on(type, callback) {
    if (!this.events[type]) {
      this.events[type] = []
    }
    this.events[type].push(callback)
  }
  // 移除订阅
  off(type, callback) {
    if (!this.events[type]) throw new Error('event dose not exist')
    this.events[type] = this.events[type].filter((item) => item !== callback)
  }
}

第三步:实现触发事件、只触发一次事件功能

javascript 复制代码
class EventEmitter {
  constructor() {
    this.events = {}
  }
  // 添加订阅
  on(type, callback) {
    if (!this.events[type]) {
      this.events[type] = []
    }
    this.events[type].push(callback)
  }
  // 移除订阅
  off(type, callback) {
    if (!this.events[type]) throw new Error('event dose not exist')
    this.events[type] = this.events[type].filter((item) => item !== callback)
  }
  // 触发事件
  emit(type, ...rest) {
    if (!this.events[type]) throw new Error('event does not exist')
    this.events[type].forEach((fn) => fn.apply(this, rest))
  }
  // 只触发一次事件,之后销毁
  once(type, callback) {
    function fn() {
      callback()
      this.off(type, fn)
    }
    this.on(type, fn)
  }
}

使用实例:

javascript 复制代码
const myEvent = new EventEmitter()
myEvent.on('click', (res) => {
  console.log('监听click事件', res)
})
myEvent.on('remove', () => {
  console.log('监听remove事件')
})
myEvent.emit('click', 'click data')
myEvent.emit('remove')
myEvent.emit('error')

与观察者模式的区别

面试中经常会问发布订阅模式和观察者模式的区别,我们需要对两者的不同有一定的了解:

  • 实现方式:在观察者模式中,观察者(Observer)通常会直接订阅(Subscribe)主题(Subject)的更新,而主题则会在状态改变时直接调用观察者的方法。而在发布订阅模式中,发布者(Publisher)和订阅者(Subscriber)通常不会直接交互,而是通过一个调度中心(Message broker 或 Event bus)来进行通信。
  • 耦合性:观察者模式中的观察者和主题之间的耦合性相对较高,因为观察者需要直接订阅主题。而在发布订阅模式中,由于引入了调度中心,发布者和订阅者之间的耦合性较低。
  • 使用场景:观察者模式通常用于处理较为简单的一对多依赖关系,例如GUI中的事件处理等。而发布订阅模式则更适合处理复杂的异步处理和跨系统通信等场景,例如消息队列、事件驱动架构等。
相关推荐
康小汪7 小时前
AI 写 Vue 总写成同一个味道:给它装 Skills,装的不是知识是边界
前端·vue.js·人工智能·ai编程·最佳实践
智能运维指南8 小时前
研制过程“两张皮“怎么破:研制一体化支撑平台的定位、能力边界与落地前提
java·前端·人工智能·嘉为蓝鲸
白山编程大哥10 小时前
Java 后端如何优雅地把 List 集合返回给前端
java·前端·list
Flynt11 小时前
我把热榜那篇"禁用 axios"逐条实测了一遍:结论大体对,坑在它没讲的地方
前端·javascript·axios
Csvn11 小时前
bundle优化
前端
北冥有鱼12 小时前
发版后动态路由点击报 `Failed to fetch dynamically imported module`」问题上的完整排查与修复过程
前端·vue.js
静默回滚12 小时前
视频压到 25 MB 以内,码率要算、音轨要扣、余量要留
前端
用户372037492601812 小时前
把 10MB 中文语义模型塞进浏览器:STSB 做到教师模型的 93%,但线上 top1 只有 42%
前端
光锥智能12 小时前
海康机器人举行2026移动机器人新品发布会:箱式存拣升级,「明智」系列发布
java·前端·机器人
计算机魔术师12 小时前
Anthropic 上市文件最吓人的一幕,不是亏损 807 亿
前端