如何在Node.js Express中正常使用EventEmitter?
EventEmitter 在 Express 中不生效的解决方案
核心问题
EventEmitter 的事件监听仅能捕获监听器注册完成后触发的同类型事件。你的代码执行顺序错误,先调用emitter.emit('done')触发事件,之后才注册done事件的回调函数,事件触发时没有对应监听器响应,自然不会有控制台输出。
修复代码
调整事件触发和监听器注册的顺序即可,修正后代码如下:
import EventEmitter from 'events' import express from 'express' const server = express(); server.get('/view', async function (req, res) { const emitter = new EventEmitter() // 先注册事件监听器 emitter.on('done', () => { console.log('testing is running') }) // 注册完成后再触发事件 emitter.emit('done') // 补充请求响应逻辑,避免请求挂起 res.end('request handled') }) server.listen(3000, () => { console.log('服务启动在端口3000') })
其他可选实现
如果业务逻辑需要先声明事件触发逻辑,再注册监听器,可以将触发逻辑放到异步队列中,等同步逻辑(含监听器注册)执行完成后再触发事件:
server.get('/view', async function (req, res) { const emitter = new EventEmitter() // 先声明事件触发,放到宏任务队列等待执行 setImmediate(() => emitter.emit('done')) // 后注册监听器,依然可以捕获到异步触发的事件 emitter.on('done', () => { console.log('testing is running') }) res.end('request handled') })
注意事项
- 每个请求内创建的
EventEmitter是独立实例,仅在当前请求生命周期内生效,不会和其他请求的实例冲突,请求结束后会自动被垃圾回收。 - 如果是需要跨请求复用的全局事件实例,不要在请求处理函数内部创建,提到全局作用域声明即可。
内容的提问来源于stack exchange,提问作者Hypothesis
相关产品推荐
相关产品推荐

