手写发布订阅模式

手写实现一个简易的发布订阅模式,通常有以下几个关键点:

  1. 订阅(subscribe):用户订阅特定的事件,当该事件触发时,执行与事件关联的回调函数。

  2. 发布(publish):当某个事件发生时,发布该事件,并通知所有订阅了该事件的回调函数。

发布订阅模式实现

我们可以创建一个 EventEmitter 类,实现 subscribe、unsubscribe(取消订阅)和 publish(发布)方法。

实现代码:

class EventEmitter {

constructor() {

// 存储事件名和对应的订阅者列表

this.events = {};

}

// 订阅事件

subscribe(event, listener) {

if (!this.eventsevent) {

this.eventsevent = \[\];

}

this.eventsevent.push(listener); // 将订阅者(回调函数)添加到事件的订阅者列表

return () => this.unsubscribe(event, listener); // 返回取消订阅的函数

}

// 取消订阅

unsubscribe(event, listener) {

const listeners = this.eventsevent;

if (!listeners) return;

复制代码
const index = listeners.indexOf(listener);
if (index !== -1) {
  listeners.splice(index, 1);  // 移除指定的回调函数
}

}

// 发布事件

publish(event, ...args) {

const listeners = this.eventsevent;

if (!listeners) return;

复制代码
listeners.forEach(listener => listener(...args));  // 执行每个订阅者的回调

}

}

说明:

  1. subscribe:

如果事件尚未存在,则为该事件创建一个空数组。

将订阅者(即回调函数)推入事件对应的数组中。

返回一个取消订阅的函数,方便用户手动移除某个事件的订阅。

  1. unsubscribe:

用于取消订阅,查找指定事件的回调函数并从订阅者列表中移除它。

  1. publish:

用于触发事件,通知所有订阅者。

通过 forEach 遍历事件对应的回调列表,执行每个回调函数。

使用示例:

const emitter = new EventEmitter();

// 订阅事件

const onUserLogin = (username) => {

console.log(${username} has logged in!);

};

const onUserLogout = (username) => {

console.log(${username} has logged out!);

};

const unsubscribeLogin = emitter.subscribe('login', onUserLogin);

const unsubscribeLogout = emitter.subscribe('logout', onUserLogout);

// 发布事件

emitter.publish('login', 'john_doe'); // 输出: john_doe has logged in!

emitter.publish('logout', 'john_doe'); // 输出: john_doe has logged out!

// 取消订阅

unsubscribeLogin(); // 取消登录事件的订阅

emitter.publish('login', 'jane_doe'); // 不会输出任何信息,因为已经取消订阅

// 再次发布注销事件

emitter.publish('logout', 'jane_doe'); // 输出: jane_doe has logged out!

扩展:

如果需要支持一次性事件(例如订阅者只想接收一次事件),可以实现一个 once 方法,订阅后自动取消订阅。

还可以支持事件参数的筛选、优先级等功能。

总结:

该实现提供了一个简单的发布订阅系统,支持事件的订阅、取消订阅和发布。

通过此模式,事件的发布者与订阅者之间解耦,适合用于异步通信、消息推送、事件驱动的编程等场景。

如果你需要进一步的功能扩展或者有其他问题,随时告诉我!

相关推荐
CharlesYu0111 小时前
前端性能优化的第一性原理,是不断缩短“用户发起意图 → 获得可用结果”之间的时间
前端
平头哥技术团队11 小时前
Day 21 _ 页内锚点_给每段起个 id,目录写 href=_#id_,点一下页面就滚到那一段
前端·html·html5
子兮曰12 小时前
Bun v1.4.1 深度解析:从 Zig 到 Rust,一场 11 天、64 个 AI 代理的语言迁徙
前端·后端·bun
人民广场吃泡面12 小时前
什么是AI Agent?它又能给前端带来哪些效率提升?
前端·人工智能
中科三方13 小时前
两家域名注册商资质被ICANN终止:企业域名资产安全再受关注
前端·网络·安全·域名
bug总结13 小时前
uniapp vue3全局方法注册使用
前端·javascript·uni-app
华无丽言14 小时前
如何在宜搭中实现获取子表中的字段值赋值到父表中?
前端·javascript·低代码
IT_陈寒14 小时前
Vue的computed属性竟然坑了我一把
前端·人工智能·后端
威斯软科的老司机14 小时前
通俗讲解 CNN 图像识别、向量 Embedding、Softmax 概率计算这三块的简化原理
前端·人工智能·ui·数字孪生
泯泷15 小时前
手搓JSVM第 12 篇:完整最小 JSVM 实现与源码设计复盘
前端·javascript·前端框架