
events
模块是 Node.js 内置的一个 事件驱动机制模块 ,提供了发布/订阅模式(观察者模式)的实现。几乎所有 Node.js 核心模块(如
http
、fs
、net
、stream
)都是基于events
模块实现的。
核心类是 EventEmitter
,通过它我们可以注册事件、触发事件、移除事件监听等。
一、引入模块
javascript
const EventEmitter = require('events');
const emitter = new EventEmitter();
二、EventEmitter
的所有 API
1. 事件监听相关
API | 说明 | 示例 |
---|---|---|
emitter.on(eventName, listener) |
为指定事件添加一个监听器,事件可以被多次监听 | emitter.on('data', msg => console.log(msg)); |
emitter.addListener(eventName, listener) |
on 的别名 |
|
emitter.once(eventName, listener) |
注册一次性监听器,触发一次后自动移除 | emitter.once('login', user => console.log(user)); |
emitter.prependListener(eventName, listener) |
将监听器添加到监听队列的开头(默认是结尾) | |
emitter.prependOnceListener(eventName, listener) |
同上,但只执行一次 |
2. 事件触发相关
API | 说明 | 示例 |
---|---|---|
emitter.emit(eventName[, ...args]) |
触发事件,并传递参数给监听器 | emitter.emit('data', 'hello'); |
emitter.listenerCount(eventName) |
获取某个事件的监听器数量 | |
emitter.listeners(eventName) |
返回一个数组,包含所有监听器函数 | |
emitter.rawListeners(eventName) |
返回监听器数组(包含 once 包装的原始函数) |
3. 移除监听器相关
API | 说明 | 示例 |
---|---|---|
emitter.off(eventName, listener) |
移除某个监听器(Node v10+ 推荐) | |
emitter.removeListener(eventName, listener) |
off 的旧写法 |
|
emitter.removeAllListeners([eventName]) |
移除指定事件或所有事件的监听器 |
4. 事件属性设置
API | 说明 | 示例 |
---|---|---|
emitter.eventNames() |
返回所有注册过的事件名数组 | |
emitter.setMaxListeners(n) |
设置某个 EventEmitter 实例的最大监听器数量(默认 10,超过会有警告) |
|
emitter.getMaxListeners() |
获取最大监听数 | |
emitter.defaultMaxListeners |
静态属性,所有实例默认的最大监听数 |
5. 继承 EventEmitter
几乎所有自定义类都可以继承 EventEmitter
,从而具备事件驱动能力。
javascript
const EventEmitter = require('events');
class MyServer extends EventEmitter {
start() {
console.log('Server starting...');
this.emit('start', Date.now());
}
}
const server = new MyServer();
server.on('start', time => console.log('Started at:', time));
server.start();
三、常用 API 总结
最常用的 API 有以下几个:
-
on / once → 注册事件监听
-
emit → 触发事件
-
off / removeListener → 移除监听
-
setMaxListeners / getMaxListeners → 解决内存泄漏警告
-
listenerCount → 查看监听器数量(调试常用)
四、典型使用场景
1. 异步回调替代方案
javascript
const emitter = new EventEmitter();
function fetchData() {
setTimeout(() => {
emitter.emit('data', { user: 'Alice' });
}, 1000);
}
emitter.on('data', data => {
console.log('接收到数据:', data);
});
fetchData();
2. 发布-订阅模式
多个模块之间通过事件通信,而不是直接调用:
javascript
// publisher.js
const EventEmitter = require('events');
const bus = new EventEmitter();
module.exports = bus;
// subscriberA.js
const bus = require('./publisher');
bus.on('orderCreated', order => console.log('通知A处理:', order));
// subscriberB.js
const bus = require('./publisher');
bus.on('orderCreated', order => console.log('通知B处理:', order));
// main.js
const bus = require('./publisher');
bus.emit('orderCreated', { id: 1, product: 'iPhone' });
3. 流 (Stream) 内部机制
stream
模块的 data
, end
, error
都是基于 events
实现。
javascript
const fs = require('fs');
const readStream = fs.createReadStream('./file.txt');
readStream.on('data', chunk => console.log('读取:', chunk.toString()));
readStream.on('end', () => console.log('读取完成'));
4. 错误处理
事件驱动模型下,必须捕获 error
事件,否则程序会崩溃。
javascript
emitter.on('error', err => console.error('捕获错误:', err));
emitter.emit('error', new Error('出错了'));
5. 大型系统中的消息总线
在 Node.js 微服务或大型项目中,可以用 EventEmitter
做应用内的 事件总线,用于模块解耦。
五、注意事项
-
没有监听
error
事件会导致程序崩溃。 -
默认最大监听器是 10 ,超出会有内存泄漏警告,需要
setMaxListeners()
。 -
同步执行:事件监听器默认是同步执行的,要避免阻塞主线程。
- 如果想异步执行,可以用
process.nextTick()
或setImmediate()
包装。
- 如果想异步执行,可以用
✅ 总结下来:
-
events
模块的核心是EventEmitter
,实现了 观察者模式。 -
最常用的方法:
on
/once
/emit
/off
/setMaxListeners
。 -
使用场景包括:模块通信、流处理、错误捕获、消息总线、异步任务管理。