做什么

Node 的事件机制——许多内置对象(HTTP server、Stream、process)都基于 EventEmitter。

import { EventEmitter } from 'events';

const bus = new EventEmitter();

bus.on('message', (data) => console.log('got:', data));
bus.emit('message', 'hello');                    // got: hello

5 个核心方法

ee.on('event', fn)              // 订阅
ee.once('event', fn)            // 只触发一次后自动取消
ee.off('event', fn)             // 取消(等同 removeListener)
ee.emit('event', ...args)       // 触发
ee.removeAllListeners('event')  // 移除某事件所有监听
ee.listenerCount('event')       // 几个监听器

实战:用作模块间通信

// bus.js
import { EventEmitter } from 'events';
export const bus = new EventEmitter();

// auth.js
import { bus } from './bus.js';
bus.emit('user:login', { id: 42, name: 'Alice' });

// analytics.js
import { bus } from './bus.js';
bus.on('user:login', user => {
    console.log(`User ${user.name} logged in`);
});

内置 EventEmitter 例子

// HTTP server
server.on('request', (req, res) => { ... });
server.on('connection', socket => { ... });
server.on('error', err => { ... });
server.on('close', () => { ... });

// Stream
readable.on('data', chunk => { ... });
readable.on('end', () => { ... });
readable.on('error', err => { ... });

// Process
process.on('SIGINT', () => { ... });

内存泄漏防护

// 默认警告阈值
ee.getMaxListeners()                         // 10

// 调高
ee.setMaxListeners(20);

// 或全局调高(一般不用)
require('events').defaultMaxListeners = 20;

看到 "MaxListenersExceededWarning" 警告通常是真的 bug——某处反复 .on() 没移除:

// ❌ 每次请求都新加监听
server.on('request', (req, res) => {
    db.on('error', () => res.status(500));   // 每个请求加一个,永不移除
});

// ✓ 用 once,或在生命周期结束时移除
server.on('request', (req, res) => {
    const handler = () => res.status(500);
    db.once('error', handler);
    res.on('close', () => db.off('error', handler));
});

error 事件特殊

ee.emit('error', new Error('boom'));         // 没监听 → **进程崩**

所有 EventEmitter 都该监听 error

ee.on('error', err => console.error(err));

once 返回 Promise

import { once } from 'events';

// 老式
ee.once('ready', () => start());

// 新式(async/await 友好)
await once(ee, 'ready');
start();

取消所有监听

ee.removeAllListeners();                     // 所有事件所有监听
ee.removeAllListeners('event');              // 仅某事件

自定义类继承

class MyApp extends EventEmitter {
    start() {
        this.emit('start');
    }
}

const app = new MyApp();
app.on('start', () => console.log('started'));
app.start();

同步触发

emit 是同步的——所有监听器在 emit 同一栈里跑:

ee.on('e', () => console.log('1'));
ee.on('e', () => console.log('2'));
console.log('before');
ee.emit('e');
console.log('after');

// 输出:before 1 2 after

如果监听器抛错 → emit 调用方收到。

异步触发:

import { setImmediate } from 'timers/promises';
ee.on('e', async () => {
    await setImmediate();        // 放到下个 tick
    console.log('async');
});

现代替代

很多场景用 Promise / async iterator 替代 EventEmitter

// ❌ EventEmitter 风格
ee.on('data', chunk => process(chunk));
ee.on('end', () => done());

// ✓ Async iterator(如果可用)
for await (const chunk of stream) {
    process(chunk);
}

  • emit error 没监听 → 进程崩
  • .on() 不配对 .off() → 内存泄漏
  • 监听器太多 → MaxListeners 警告
  • emit 是同步的——监听器拖时间会阻塞调用方

下一篇:http 模块。