1 背景
因为考虑到软件分层,我们的指标上报不能在同一个文件里面实现,所以考虑通过事件的方式,事件监听和触发分开。只要触发该事件,我们就可以执行相关逻辑来上报指标。
2 使用 eventemitter3 库
使用事件的方式,外部监听事件,当需要上报的时候触发事件执行上报。
可以考虑使用第三方开源库来实现 eventemitter3。
触发事件的文件:
import EventEmitter from 'eventemitter3';
export enum EventType {
Type1 = 'type1',
type2 = 'type2',
}
export class MyCenter extends EventEmitter<EventType> {
// 触发事件执行上报逻辑
this.emit(EventType.Type1, {
options,
...
});
}
监听事件的文件:
// 全局初始化的时候,监听事件
(()=>{
MyCenter.addListener(EventType.Type1, (event: EventData) => {
// export metrics
// 执行触发该事件需要的逻辑
});
})()
3 自己写事件监听
// EventEmitter.ts
export enum EventType {
Type1 = 'type1',
type2 = 'type2',
}
class EventEmitter {
// 保存事件的回调函数
listeners: {
[key in EventName]: Set<(event: EventName, data: any) => unknown>;
} = {
[EventName.Type1]: new Set(),
[EventName.Type2]: new Set(),
};
// 触发
emit(event: EventName, data?: any) {
const listeners = this.listeners[event];
if (listeners) {
for (const listener of listeners) {
listener(event, data); // 执行addListener的回调函数
}
}
}
// 监听
addListener(event: EventName, callback: (event: EventName, data: any) => unknown) {
const listeners = this.listeners[event];
if (listeners) {
listeners.add(callback);
}
return {
remove: () => {
if (listeners) {
listeners.delete(callback);
}
},
};
} }
// MyCenter.ts
export class MyCenter extends EventEmitter {
// 触发事件执行上报逻辑
this.emit(EventType.Type1, {
options,
...
});
}
4 扩展
tracing的批量上报也用到了事件的方式。当用户操作触发某些事件的时候,会自动把当前所有数据上报,避免数据丢失。
同时一些组件之间的通信也可以考虑使用事件。
5 浏览器 & node 的事件机制
浏览器事件机制:
- 浏览器中的事件机制是基于事件循环(Event Loop)的。事件循环是一个持续运行的循环,用于监听和处理事件。
- 当事件发生时,浏览器会将事件添加到事件队列中。
- 事件队列中的事件按照顺序依次被处理。每次处理一个事件时,浏览器会检查是否有相关的事件处理程序(事件监听器)注册在该事件上。
- 如果有注册的事件处理程序,浏览器将调用该处理程序来响应事件。
- 浏览器事件机制还包括事件捕获和事件冒泡两个阶段。事件捕获从最外层元素向内层元素传递,事件冒泡则相反,从内层元素向外层元素传递。
Node.js 事件机制:
- Node.js 采用了事件驱动的非阻塞 I/O 模型。它使用 EventEmitter 类来处理事件。
- 在 Node.js 中,事件由事件发射器(EventEmitter)发出,并被一个或多个事件监听器(Event Listener)捕获和处理。
- EventEmitter 是一个可以绑定和触发事件的对象。通过继承 EventEmitter 类,可以创建自定义的事件发射器。
- 事件监听器可以通过 on 方法或 addListener 方法注册到事件发射器上。
- 当事件发生时,事件发射器会按照注册的顺序依次调用事件监听器来处理事件。
- Node.js 的事件机制是单线程的,事件处理是异步的,不会阻塞主线程的执行。
总结:
- 浏览器和 Node.js 的事件机制都是基于事件的,但在实现上有一些差异。浏览器使用事件循环和事件队列来处理事件,而 Node.js 使用 EventEmitter 类来处理事件。了解这些事件机制对于编写响应式和高效的代码非常重要。
6 组件通信 EventBus
EventBus:一种设计模式,即 发布-订阅,使用事件监听+触发的方式,进而实现组件间的通信。
不同组件间的通信,常见的写法是使用回调函数和ref的方式,但是这种方式,对于组件层级比较大的情况下,组件间的耦合度比较高,所以,考虑一种解耦的处理方式是通过eventBus来实现,模块监听各自关注的事件,同时也可以通过事件抛出模块数据。