警告:可能的 EventEmitter - 运行“foundation new”时的节点警告

Posted

技术标签:

【中文标题】警告:可能的 EventEmitter - 运行“foundation new”时的节点警告【英文标题】:Warning: Possible EventEmitter - Node warning when running `foundation new` 【发布时间】:2017-01-08 07:54:02 【问题描述】:

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

(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

节点号始终不同,但警告和警告数始终相同。我该如何解决这个问题?

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

【问题讨论】:

各种解释见***.com/questions/9768444/…。 【参考方案1】:

在有关 EventEmitter memory leaks 的博客文章中找到了此材料,但在此处发布了详细信息,因此此答案不是仅链接的答案。我不相信材料本身,只是找到它并创建一个答案,以便 *** 可以看到它。

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

(node) 警告:检测到可能的 EventEmitter 内存泄漏。 11个 听众补充道。使用emitter.setMaxListeners() 增加限制。

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

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)
  )

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

(node) 警告:检测到可能的 EventEmitter 内存泄漏。 11 增加了一个听众。使用emitter.setMaxListeners() 增加限制。

您不断向错误和结束添加处理程序,但没有删除它们,即使数据已成功读取并且这些处理程序不再相关。

清理您的事件处理程序

清理处理程序的正确方法是确保在 promise 解决后,添加一个由 0 个事件处理程序组成的网络:

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。

并发处理程序

如果你想在同一个发声器上有多个监听器怎么办?例如,你可能有很多函数监听同一个发射器:

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) 的代码(尤其是开源代码),请发出拉取请求来修复它!不要走捷径!

【讨论】:

以上是关于警告:可能的 EventEmitter - 运行“foundation new”时的节点警告的主要内容,如果未能解决你的问题,请参考以下文章

检测到套接字 io 可能的 EventEmitter 内存泄漏

使用events.EventEmitter 控制Node.js 程序执行流程

(节点:6261)MaxListenersExceededWarning:检测到可能的 EventEmitter 内存泄漏

Winston - MaxListenersExceededWarning:检测到可能的 EventEmitter 内存泄漏

nodejs Websocket服务器 - 检测到可能的EventEmitter内存泄漏

MaxListenersExceededWarning:检测到可能的 EventEmitter 内存泄漏。添加了 11 个消息列表。使用emitter.setMaxListeners() 增加限制