警告:可能的EventEmitter – 运行`foundation new`时出现节点警告

每次我在CLI中运行foundation new来启动一个新的基础项目时,我会得到一长串节点警告:

 (node:15500) Warning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit (node:15500) Warning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit (node:15500) Warning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit (node:15500) Warning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit (node:15500) Warning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit (node:15500) Warning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit (node:15500) Warning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit (node:15500) Warning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit (node:15500) Warning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit (node:15500) Warning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit (node:15500) Warning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit (node:15500) Warning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit (node:15500) Warning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit (node:15500) Warning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit (node:15500) Warning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit (node:15500) Warning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit (node:15500) Warning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit (node:15500) Warning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit (node:15500) Warning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit (node:15500) Warning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit (node:15500) Warning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit (node:15500) Warning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit 

节点号总是不同的,但警告和警告的数量总是相同的。 我怎样才能解决这个问题?

这些警告显示后,其他一切似乎运行良好,项目创build。 我不确定是否应该担心警告。

在博客文章上find关于EventEmitter内存泄漏的资料,但是在这里发布了详细信息,所以这个答案不是链接唯一的答案。 我不记得材料本身,只发现它并创build一个答案,所以它是可见的Stackoverflow。

在node.js和io.js中,你最终会看到这个错误信息:

(节点)警告:检测到可能的EventEmitter内存泄漏。 一位听众补充说。 使用emitter.setMaxListeners()来增加限制。

什么时候会发生泄漏? 当您连续添加事件处理程序而不删除它们时会发生泄漏。 当你多次使用单个发射器实例时,会发生这种情况。 让我们来创build一个返回stream中下一个值的函数:

 function next(stream) { // if the stream has data buffered, return that { let data = stream.read() if (data) return Promise.resolve(data) } // if the stream has already ended, return nothing if (!data.readable) return Promise.resolve(null) // wait for data return new Promise(function (resolve, reject) { stream.once('readable', () => resolve(stream.read())) stream.on('error', reject) stream.on('end', resolve) }) } 

每次在stream中调用next()时,都会在可读,错误和结束处添加处理程序。 在接下来的第11个(stream)调用中,您将收到错误消息:

(节点)警告:检测到可能的EventEmitter内存泄漏。 一位听众补充说。 使用emitter.setMaxListeners()来增加限制。

您不断地将error handling程序添加到错误并结束,但是并没有删除它们,即使数据已成功读取且处理程序不再相关。

清理你的事件处理程序

清理你的处理程序的正确方法是确保在承诺解决之后,添加一个0事件处理程序的networking:

 return new Promise(function (resolve, reject) { stream.on('readable', onreadable) stream.on('error', onerror) stream.on('end', cleanup) // define all functions in scope // so they can be referenced by cleanup and vice-versa function onreadable() { cleanup() resolve(stream.read()) } function onerror(err) { cleanup() reject(err) } function cleanup() { // remove all event listeners created in this promise stream.removeListener('readable', onreadable) stream.removeListener('error', onerror) stream.removeListener('end', cleanup) } }) 

采用这种方法,在每个promise都解决之后就不会有事件发送者泄漏,净更改事件处理程序为0。

并发处理程序

如果你想在同一个发射器上有多个监听器呢? 例如,您可能有很多function正在侦听同一个发射器:

 doThis1(stream) doThis2(stream) doThis3(stream) doThis4(stream) doThis5(stream) doThis6(stream) doThis7(stream) doThis8(stream) doThis9(stream) doThis10(stream) doThis11(stream) doThis12(stream) doThis13(stream) 

如果上面的所有函数都将处理程序添加到数据事件中,您将得到相同的泄漏错误消息,但是您知道没有实际的泄漏。 此时,您应该相应地设置最大数量的监听器:

 return new Promise(function (resolve, reject) { // increase the maximum number of listeners by 1 // while this promise is in progress stream.setMaxListeners(stream.getMaxListeners() + 1) stream.on('readable', onreadable) stream.on('error', onerror) stream.on('end', cleanup) function onreadable() { cleanup() resolve(stream.read()) } function onerror(err) { cleanup() reject(err) } function cleanup() { stream.removeListener('readable', onreadable) stream.removeListener('error', onerror) stream.removeListener('end', cleanup) // this promise is done, so we lower the maximum number of listeners stream.setMaxListeners(stream.getMaxListeners() - 1) } }) 

这允许您确认限制并保持事件处理的控制权,同时允许node.js在发生实际泄漏时输出错误消息。

帮助写出更好的代码!

如果你只是.setMaxListener(0),那么你可能会在不知不觉中泄漏。 如果您看到任何使用.setMaxListeners(0)的代码(尤其是开源代码),请发出pull请求来解决它! 不要走捷径!