如何使用 JavaScript 实现一个简单的发布-订阅模式?

推荐答案

-- -------------------- ---- -------
----- ------------ -
  ------------- -
    ----------- - ---
  -

  ------------- --------- -
    -- ------------------------- -
      ---------------------- - ---
    -
    --------------------------------------
  -

  --------------- -------- -
    -- ------------------------ -
      --------------------------------------- -- -
        ------------------
      ---
    -
  -

  -------------- --------- -
     -- ------------------------- -
        -------
    -

    --------------
        ------ -----------------------
        ------
    -
    ---------------------- - -------------------------------- -- -- --- ----------
  -
-


-- ----
----- ------- - --- ---------------

----- ---------- - --------- -- -
  ----------------------- ---------
--

----- ---------- - --------- -- -
   ------------------------ --------
-


--------------------- ------------
--------------------- ------------

----------------------- ------- --------- -- --- -------- ------ ------ -------- ------ ------
---------------------------------
----------------------- ------ ------ ------------- -- --- -------- ----- ------ ----------
----------------------
----------------------------- ------ --- ------- ------- -- -------

本题详细解读

发布-订阅模式的概念

发布-订阅模式(Publish-Subscribe Pattern)是一种消息传递模式,它允许组件(发布者)发布消息,而无需知道哪些组件(订阅者)会接收这些消息。订阅者订阅感兴趣的消息类型,当发布者发布相应类型的消息时,订阅者会收到通知。这种模式实现了组件之间的松耦合,使得系统更易于扩展和维护。

实现思路

  1. 事件存储: 使用一个对象 this.events 来存储事件及其对应的回调函数列表。键为事件名称(eventName),值为回调函数数组。
  2. on 方法(订阅):
    • 接收两个参数:事件名称 eventName 和回调函数 callback
    • 如果 this.events 中不存在 eventName 的键,则创建一个新的空数组。
    • callback 添加到 this.events[eventName] 数组中。
  3. emit 方法(发布):
    • 接收一个参数:事件名称 eventName 和可变数量的参数 ...args,这些参数会传递给回调函数。
    • 检查 this.events 中是否存在 eventName 的键。
    • 如果存在,则遍历 this.events[eventName] 数组中的所有回调函数,并使用 ...args 调用每一个回调函数。
  4. off 方法(取消订阅):
    • 接收两个参数:事件名称 eventName 和可选的回调函数 callback
    • 检查 this.events 中是否存在 eventName 的键,如果不存在则直接返回。
    • 如果未传入 callback, 则删除 this.events[eventName] 所有订阅的事件。
    • 如果传入了 callback,则过滤 this.events[eventName] 中的回调函数,将不等于 callback 的函数保留下来,以此移除指定的订阅。

代码详解

  • class EventEmitter: 定义一个 EventEmitter 类来封装发布-订阅逻辑。
  • constructor(): 初始化 this.events 为空对象。
  • on(eventName, callback): 实现了订阅功能,将回调函数添加到指定事件的回调数组中。
  • emit(eventName, ...args): 实现了发布功能,遍历并执行指定事件的所有回调函数。
  • off(eventName, callback): 实现了取消订阅功能,移除指定事件或指定事件下的指定回调函数。

示例代码解释

示例代码创建了一个 EventEmitter 实例,并使用 on 方法订阅了 message 事件的两个回调函数 logMessagelogWarning。 当使用 emit('message', 'Hello, world!') 发布消息时,两个回调函数都会被调用。之后调用 off 移除 logMessage , 再次调用 emit 只会执行 logWarning, 最后调用off('message') 移除所有 message 事件的订阅,后续调用 emit 不会执行任何订阅事件。

纠错
反馈