用闭包实现事件总线的核心是封装 handlers 对象与 on/off/emit 方法,确保事件监听器隔离、支持多回调、精确移除、参数透传且不污染全局。

<p>用闭包实现事件总线的核心,是把事件监听器列表和触发逻辑封装在私有作用域里,避免全局污染,同时提供干净的 <code>on</code>、<code>off</code>、<code>emit</code> 接口。</p> <h3>封装事件映射表与操作方法</h3> <p>闭包内部维护一个对象 <code>handlers</code>,键为事件名,值为监听函数数组。所有增删查都只通过返回的公共方法进行,外部无法直接访问或修改内部状态。</p> <p>关键点:每个事件名对应独立的监听器数组,支持同一事件绑定多个回调;取消订阅时精确匹配函数引用(不能靠名字或字符串),所以必须保留原始函数引用。</p> <h3>提供 on(订阅)与 off(取消)方法</h3> <p><code>on(eventName, callback)</code> 将回调推入对应事件的数组;<code>off(eventName, callback)</code> 遍历并用 <code>===</code> 移除指定函数(注意不是 <code>splice(0,1)</code> 这种盲目删除)。</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill3430" title="Alibabacloud Sdk Client Initialization For Java"><img src="https://img.php.cn/upload/skill/000/000/081/178955835420587.jpg" alt="Alibabacloud Sdk Client Initialization For Java" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill3430" title="Alibabacloud Sdk Client Initialization For Java" class="overflowclass">Alibabacloud Sdk Client Initialization For Java</a> <p class="overflowclass">在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。</p> </div> <a rel="nofollow" href="/xiazai/skill3430" title="Alibabacloud Sdk Client Initialization For Java" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div>
- 如果没传
callback,可支持清空该事件所有监听器 - 确保重复
on同一函数不会重复添加(可选增强) -
off时若函数不存在,静默忽略,不报错
实现 emit(触发)并支持参数透传
emit(eventName, ...args) 查找该事件的所有监听器,按注册顺序依次调用,并把参数原样传入。若事件无监听器,不报错也不做任何事。
可选增强:支持异步触发(用 Promise.all 并行执行)或顺序等待(reduce + async/await),但基础版本保持同步即可。
完整可运行示例
下面是一个轻量、无依赖的实现:
function createEventBus() {
const handlers = {};
return {
on(eventName, callback) {
if (!handlers[eventName]) {
handlers[eventName] = [];
}
handlers[eventName].push(callback);
},
off(eventName, callback) {
if (!handlers[eventName]) return;
if (!callback) {
handlers[eventName] = [];
return;
}
const index = handlers[eventName].indexOf(callback);
if (index > -1) {
handlers[eventName].splice(index, 1);
}
},
emit(eventName, ...args) {
const callbacks = handlers[eventName];
if (callbacks && callbacks.length) {
callbacks.forEach(cb => cb(...args));
}
}
};
}
// 使用示例:
const bus = createEventBus();
const handler1 = () => console.log('收到消息');
const handler2 = (msg) => console.log('带参:', msg);
bus.on('login', handler1);
bus.on('login', handler2);
bus.emit('login', 'success'); // 输出两行
bus.off('login', handler1);
bus.emit('login', 'again'); // 只输出第二行
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










