闭包实现的轻量Pub/Sub事件总线通过立即执行函数封装私有events对象,提供on、emit、off、once方法,确保数据私有、接口简洁且实例隔离。

用闭包实现一个轻量发布订阅(Pub/Sub)事件总线,核心是把事件监听器列表和触发逻辑封装在函数作用域内,避免全局污染,同时保证数据私有性和接口简洁。
闭包封装事件存储与操作
定义一个立即执行函数,返回包含 on(订阅)、emit(发布)、off(取消订阅)方法的对象。所有事件名对应的回调数组都存在闭包内的局部对象 events 中,外部无法直接访问。
示例代码:
const EventBus = (function () {
const events = {}; // 私有存储:{ 'click': [fn1, fn2], 'data': [fn3] }
return {
on(event, callback) {
if (!events[event]) events[event] = [];
events[event].push(callback);
},
emit(event, ...args) {
if (events[event]) {
events[event].forEach(cb => cb(...args));
}
},
off(event, callback) {
if (!events[event]) return;
if (!callback) {
delete events[event]; // 清空整个事件
} else {
events[event] = events[event].filter(cb => cb !== callback);
}
}
};
})();
支持一次性订阅(once)
在基础版本上扩展 once 方法:注册后执行一次就自动解绑。利用闭包保存原始回调,并在内部调用后主动调用 off。
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
添加方式(接在上面的 return 对象中):
once(event, callback) {
const onceCallback = (...args) => {
callback(...args);
this.off(event, onceCallback);
};
this.on(event, onceCallback);
}
防止重复绑定与错误处理
实际使用中容易重复 on 同一回调,导致多次触发。可在 on 中加简单去重(仅对引用相等的函数):
- 检查回调是否已存在,避免重复 push
-
emit前判断事件是否存在,避免报错 -
off传入不存在的事件名时静默处理,不抛错
使用示例
订阅、发布、取消都很直观:
EventBus.on('user:login', (user) => console.log('欢迎', user.name));
EventBus.on('user:logout', () => console.log('已登出'));
EventBus.emit('user:login', { name: '张三' }); // 欢迎 张三
EventBus.emit('user:logout'); // 已登出
// 取消某个监听
const handler = () => console.log('只执行一次');
EventBus.once('test', handler);
EventBus.emit('test'); // 打印后自动解绑
EventBus.emit('test'); // 无输出
不复杂但容易忽略细节:闭包让 events 持久存在且不可篡改,每个实例彼此隔离;若需多个独立总线,可把整个结构封装成工厂函数,每次调用返回新闭包环境。

















