每次我在CLI中运行foundation new
以启动新的Foundation项目时,我都会收到很长的Node警告列表:
(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
节点编号始终不同,但警告和警告数始终相同。我该如何解决这个问题?
在这些警告显示之后,其他所有内容似乎都运行正常并且项目已创建。我不确定我是否应该担心这些警告。
答案 0 :(得分:2)
在关于EventEmitter memory leaks的博客文章中找到此资料,但在此处发布详细信息,因此此答案不是仅限链接的答案。我不相信材料本身,只找到它并创建一个答案,以便Stackoverflow可以看到它。
在node.js和io.js中,您最终会看到以下错误消息:
(节点)警告:检测到可能的EventEmitter内存泄漏。 11 a 听众补充道。使用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个下一个(流)调用中,您将收到错误消息:
(节点)警告:检测到可能的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)的任何代码(特别是开源),请发出拉取请求来修复它!不要做捷径!