内置的模式•EventEmitter
在 Node.js 中,EventEmitter 用于实现事件驱动的编程模型。
它提供一个事件处理机制,让开发者能够在程序中轻松地监听和触发事件。
EventEmitter的用法
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {};
const myEmitter = new MyEmitter();
// 监听自定义事件
myEmitter.on('customEvent', (data) => {
console.log('Received data:', data);
});
// 触发自定义事件
myEmitter.emit('customEvent', { message: 'Hello, EventEmitter!' });
EventEmitter 的优点
- 异步处理:通知机制(例如发送电子邮件和处理大量数据)可能非常耗时,EventEmitter 启用异步处理,允许程序继续响应其他请求,而无需等待通知完成
- 模块化和解耦:EventEmitter 能够将通知机制与核心逻辑分开,只需发出事件,核心逻辑不需要知道通知是如何传递的
EventEmitter 的方法
方法名 | 参数 | 描述 |
---|---|---|
on | eventName,listener | 添加事件监听器 |
emit | eventName,...args | 触发指定事件,并传递给定的参数给监听器 |
off | eventName,listener | 从指定事件的监听器数组中移除特定监听器,如果一个监听器已经被多次添加,需要多次调用来移除 |
once | eventName,listener | 添加一次性事件监听器,监听器将在下一次事件触发后被自动移除 |
eventNames | - | 返回 EventEmitter 实例注册了哪些事件的数组 |
EventEmitter的模拟实现
export interface Listener {
cb: Function;
once: boolean;
}
export interface EventsType {
[eventName: string]: Listener[];
}
export default class EventHub {
// 所有事件的监听器
es: EventsType = {};
on(eventName: string, cb: Function, once: boolean = false) {
if (!this.es[eventName]) {
this.es[eventName] = [];
}
this.es[eventName].push({
cb,
once,
});
}
once(eventName: string, cb: Function) {
this.on(eventName, cb, true);
}
emit(eventName: string, ...params: any[]) {
const listeners = this.es[eventName] || [];
let l = listeners.length;
for (let i = 0; i < l; i++) {
const { cb, once } = listeners[i];
cb.apply(this, params);
if (once) {
listeners.splice(i, 1);
i--;
l--;
}
}
}
off(eventName?: string, cb?: Function) {
// clean all
if (eventName === undefined) {
this.es = {};
} else {
if (cb === undefined) {
// clean the eventName's listeners
delete this.es[eventName];
} else {
const listeners = this.es[eventName] || [];
// clean the event and listener
let l = listeners.length;
for (let i = 0; i < l; i++) {
if (listeners[i].cb === cb) {
listeners.splice(i, 1);
i--;
l--;
}
}
}
}
}
}
/**
* const ee = new EventHub();
*
* ee.on('click', (...values) => {});
*
* ee.on('mouseover', (...values) => {});
*
* ee.emit('click', 1, 2, 3);
* ee.fire('mouseover', {}); // same with emit
*
* ee.off();
*/