javascript事件总线通过eventbus类实现批量派发,核心是用map维护事件名与处理器数组映射,支持onmany/emitmany/emitbatch等批量操作,具备去重、错误隔离、异步安全等特性。

JavaScript 中通过面向对象方式实现支持批量派发的事件总线(Event Bus),核心在于封装事件注册、触发与批量处理逻辑,同时保证事件解耦、类型安全(可选)和执行顺序可控。下面是一个轻量、可扩展、生产可用的设计方案。
1. 事件总线类的基本结构
定义一个 EventBus 类,内部维护一个事件映射表(Map 或普通对象),键为事件名,值为回调函数数组。支持单个/多个事件监听、触发,以及关键的「批量触发」能力。
使用 Map 更适合动态事件名且避免原型污染;用 WeakMap 可辅助做实例级私有状态(如用于自动清理),但此处以清晰性优先。
2. 支持批量监听与批量触发
批量派发 ≠ 多次单发。真正的批量是指:一次调用触发多个不同事件,并确保所有监听器按注册顺序、事件分组内顺序执行(不交叉)。为此需提供:
- onMany(events, handler):为多个事件名统一绑定同一处理器
-
emitMany(eventMap):传入
{ 'eventA': dataA, 'eventB': dataB }对象,一次性触发多个事件,每个事件携带各自参数 -
emitBatch(events):传入事件名数组(如
['user.login', 'stats.track']),无参批量触发(适合通知类事件)
3. 关键实现细节
✅ 去重与内存管理:相同事件+相同 handler 不重复添加;提供 off() 和 offMany() 清理接口;可选支持 handler 自动绑定 this 或传入 context。
✅ 异步安全:默认同步执行;若需异步批量(如微任务队列),可用 Promise.resolve().then(() => {...}) 包裹 emitMany 内部循环,避免阻塞主线程。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
✅ 错误隔离:单个 handler 抛错不应中断其余 handler 执行,用 try/catch 包裹每个调用。
✅ 通配符支持(可选):如 on('user.*', cb),配合 minimatch 或简易 glob 匹配,增强灵活性。
4. 一个简洁可用的实现示例
以下代码不含第三方依赖,ES6+ 环境可直接运行:
class EventBus {
constructor() {
this.events = new Map();
}
on(event, handler) {
if (!this.events.has(event)) {
this.events.set(event, []);
}
const handlers = this.events.get(event);
if (!handlers.includes(handler)) {
handlers.push(handler);
}
}
onMany(events, handler) {
events.forEach(event => this.on(event, handler));
}
off(event, handler) {
if (this.events.has(event)) {
const handlers = this.events.get(event);
const i = handlers.indexOf(handler);
if (i > -1) handlers.splice(i, 1);
if (handlers.length === 0) this.events.delete(event);
}
}
offMany(events, handler) {
events.forEach(event => this.off(event, handler));
}
emit(event, ...args) {
const handlers = this.events.get(event) || [];
for (const handler of handlers) {
try {
handler(...args);
} catch (e) {
console.error(`Event "${event}" handler error:`, e);
}
}
}
// 批量触发:每个事件独立传参
emitMany(eventMap) {
Object.entries(eventMap).forEach(([event, args]) => {
if (Array.isArray(args)) {
this.emit(event, ...args);
} else {
this.emit(event, args);
}
});
}
// 批量触发:仅事件名,无参
emitBatch(events) {
events.forEach(event => this.emit(event));
}
}
使用示例:
const bus = new EventBus();
bus.on('user.login', (user) => console.log('Login:', user.name));
bus.on('stats.track', (action) => console.log('Track:', action));
// 一次触发两个事件,各自带参
bus.emitMany({
'user.login': [{ name: 'Alice' }],
'stats.track': ['page_view']
});
// 输出:
// Login: Alice
// Track: page_view
不复杂但容易忽略的是:批量不是语法糖,而是语义升级——它让跨模块协作更声明式、更可控。结合 TypeScript 还可进一步约束 event 名类型和 payload 结构,提升工程健壮性。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










