Skip to main content

内置的模式•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 的方法

方法名参数描述
oneventName,listener添加事件监听器
emiteventName,...args触发指定事件,并传递给定的参数给监听器
offeventName,listener从指定事件的监听器数组中移除特定监听器,如果一个监听器已经被多次添加,需要多次调用来移除
onceeventName,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();
*/