浅谈发布——订阅模式

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

什么是发布订阅模式

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

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

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

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

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

我们希望调度中心具有这样的一个结构,整体是对象,keystring,代表事件名,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中的事件处理等。而发布订阅模式则更适合处理复杂的异步处理和跨系统通信等场景,例如消息队列、事件驱动架构等。
相关推荐
前端大卫2 小时前
Vue3 + Element-Plus 自定义虚拟表格滚动实现方案【附源码】
前端
却尘2 小时前
Next.js 请求最佳实践 - vercel 2026一月发布指南
前端·react.js·next.js
ccnocare2 小时前
浅浅看一下设计模式
前端
Lee川2 小时前
🎬 从标签到屏幕:揭秘现代网页构建与适配之道
前端·面试
Ticnix3 小时前
ECharts初始化、销毁、resize 适配组件封装(含完整封装代码)
前端·echarts
纯爱掌门人3 小时前
终焉轮回里,藏着 AI 与人类的答案
前端·人工智能·aigc
twl3 小时前
OpenClaw 深度技术解析
前端
崔庆才丨静觅3 小时前
比官方便宜一半以上!Grok API 申请及使用
前端
星光不问赶路人3 小时前
vue3使用jsx语法详解
前端·vue.js
天蓝色的鱼鱼3 小时前
shadcn/ui,给你一个真正可控的UI组件库
前端