Node.js 事件触发器 (Event Emitter)
Node.js - EventEmitter (事件触发器)
Section titled “Node.js - EventEmitter (事件触发器)”Node.js 事件介绍
Section titled “Node.js 事件介绍”Node.js 基于异步、事件驱动的架构运行。这意味着 Node.js 中的许多操作(例如处理网络请求、读取文件或与数据库交互)不会阻塞(block)程序执行。相反,它们在完成或发生重要情况时会触发事件(event)。
实现这一核心概念的是内置 events 模块中的 EventEmitter 类。许多 Node.js 内置对象(如 HTTP 服务器、流(stream)、子进程(child process))都继承自 EventEmitter。
EventEmitter 允许对象触发命名事件(named events),这些事件会导致函数对象(称为“监听器”或“listener”)被调用。
使用 EventEmitter 类
Section titled “使用 EventEmitter 类”你可以直接使用 EventEmitter 在自己的代码中实现观察者模式(observer pattern)。首先,导入该类:
const EventEmitter = require('events');然后,创建一个实例:
// 创建一个 eventEmitter 对象const myEmitter = new EventEmitter();emitter.on(eventName, listener)或emitter.addListener(eventName, listener): 为指定的eventName注册一个listener函数。每当该事件被触发时,此函数就会被调用。同一个事件可以添加多个监听器。emitter.emit(eventName[, ...args]): 触发(emit)指定的eventName。这会同步地按照注册顺序调用该事件的所有注册监听器,并将提供的args参数传递给它们。emitter.once(eventName, listener): 注册一个listener,它最多为指定的eventName调用一次。监听器在被调用后会自动移除。emitter.removeListener(eventName, listener)或emitter.off(eventName, listener): 移除指定事件的指定listener。emitter.removeAllListeners([eventName]): 移除所有监听器,或者仅移除指定eventName的监听器。emitter.listenerCount(eventName): 返回当前注册给指定eventName的监听器数量。
'newListener' (eventName, listener): 在添加监听器之前触发。'removeListener' (eventName, listener): 在移除监听器之后触发。'error' (err): 一个特殊事件。如果一个EventEmitter触发了'error'事件,但没有为该事件注册任何监听器,Node.js 通常会终止进程并抛出未捕获异常(uncaught exception)。因此,务必在可能触发错误的 EventEmitters 上注册错误监听器。
让我们创建一个简单的示例来演示基本用法(eventDemo.js):
const EventEmitter = require('events');
// 创建一个 emitter 实例const myEmitter = new EventEmitter();
// 1. 为 'greet' 事件注册一个监听器const listener1 = (name) => { console.log(`监听器 1: 你好, ${name}!`);};myEmitter.on('greet', listener1);
// 2. 为 'greet' 事件注册另一个监听器const listener2 = (name) => { console.log(`监听器 2: 欢迎, ${name}!`);};myEmitter.on('greet', listener2);
// 3. 为 'specialGreet' 事件注册一个一次性监听器myEmitter.once('specialGreet', (message) => { console.log(`特别问候: ${message}`);});
// 检查监听器数量console.log(`'greet' 事件的监听器数量: ${myEmitter.listenerCount('greet')}`); // 输出: 2console.log(`'specialGreet' 事件的监听器数量: ${myEmitter.listenerCount('specialGreet')}`); // 输出: 1
// 4. 触发 'greet' 事件并带一个参数console.log("\n触发 'greet' 事件...");myEmitter.emit('greet', 'Alice');// listener1 和 listener2 都会被调用
// 5. 触发 'specialGreet' 事件console.log("\n触发 'specialGreet' 事件...");myEmitter.emit('specialGreet', '这只发生一次!');// 监听器将被调用
console.log(`触发后 'specialGreet' 事件的监听器数量: ${myEmitter.listenerCount('specialGreet')}`); // 输出: 0
// 6. 移除 listener1console.log("\n移除监听器 1...");myEmitter.removeListener('greet', listener1);console.log(`移除后 'greet' 事件的监听器数量: ${myEmitter.listenerCount('greet')}`); // 输出: 1
// 7. 再次触发 'greet'console.log("\n再次触发 'greet' 事件...");myEmitter.emit('greet', 'Bob');// 现在只有 listener2 会被调用
// 8. 错误处理myEmitter.on('error', (err) => { console.error('--- 发生错误 ---'); console.error(err.message);});
console.log("\n触发一个 'error' 事件...");myEmitter.emit('error', new Error('发生了一些错误!'));// 如果没有注册错误监听器,程序会在这里崩溃。
console.log('\n程序结束.');运行脚本:
$ node eventDemo.js预期输出:
Listeners for 'greet': 2Listeners for 'specialGreet': 1
Emitting 'greet' event...Listener 1: 你好, Alice!Listener 2: 欢迎, Alice!
Emitting 'specialGreet' event...特别问候: 这只发生一次!Listeners for 'specialGreet' after emit: 0
Removing listener 1...Listeners for 'greet' after removal: 1
Emitting 'greet' event again...Listener 2: 欢迎, Bob!
Emitting an 'error' event...--- 发生错误 ---发生了一些错误!
程序结束.此示例展示了如何注册监听器(on, once)、触发事件(emit)、检查监听器数量(listenerCount)、移除监听器(removeListener)以及处理特殊的 'error' 事件。
理解 EventEmitter 对于有效使用 Node.js 核心模块和许多依赖异步、事件驱动模式的第三方库至关重要。