
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。 - 
使用场景包括:模块通信、流处理、错误捕获、消息总线、异步任务管理。