不存在 属性:EventEmitter 内存错误而不是正确的错误消息
Non existing property: EventEmitter memory error instead of proper error message
在基于 NodeJS 6.10.2/SailsJS 0.12.13 的 JavaScript 应用程序中,几个月以来我遇到了一种奇怪的错误行为。
在 Sails 控制器中,我尝试检索文字对象的 属性:
console.log(someObject.someProperty);
console.log("I am still here!");
但是,在我的例子中 someObject
是未定义的。所以,我希望得到像 'Cannot read property someProperty of undefined.' 这样的错误 - 然后 Node.js 完全停止或代码继续(下一个 console.log
)。
相反,代码只是在那一点停止执行,我收到一个奇怪的警告:“(节点:4822)警告:检测到可能的 EventEmitter 内存泄漏。添加了 11 个关闭的侦听器。使用 emitter.setMaxListeners() 来增加上限。”但是,无法预测此错误发生的频率。有的只有一次,有的大约有 20 次。
我发现的是,它与是否已经有回复的问题有某种联系。考虑以下因素:
mySailsControllerFunction: function(req, res) {
console.log(someObject.someProperty);
console.log("I am still here!");
res.json({"foo":"dahoo"});
}
这将导致 Sending 500 ("Server Error") response: ReferenceError: someObject is not defined
- 正是我所期望的。
但是,现在我先发送一些响应,然后尝试访问我不存在的 属性,将代码变成:
mySailsControllerFunction: function(req, res) {
res.json({"foo":"dahoo"});
setTimeout(function () {
console.log("Yeah!");
console.log(someObject.someProperty);
console.log("I am still here!");
},1000);
}
然后我经常什么也得不到: 'Yeah!' 显示,但之后什么也没有。事件侦听器错误有时存在,有时不存在。很奇怪。
此外,奇怪的是,这个问题似乎与自 Sails 开始以来所经过的时间有某种联系。我将您在上面看到的代码放在 Sails 控制器函数中,该函数在客户端重新连接后立即调用。然后我尝试调整超时值,多次重启 Sails 服务器。结果:如果我将超时设置为 1 秒,则在 5 次测试中的 4 次中,我将获得正确的错误行为。持续 10 秒大约为 50%,持续 30 秒错误将始终被忽略,没有任何控制台输出。
但是,如果我将我的测试代码放在 Sails 控制器之外,我总是会通过 Node.js 获得正确的错误行为。所以,我很确定这是 Sails 的错误行为,而不是 Node。
免责声明:我不了解 Sails。所以这可能相关也可能不相关,但我的回答可能会提供一些线索。
来自 Sails 文档:
http://sailsjs.com/documentation/reference/response-res/res-json
This method is terminal, meaning it is generally the last line of code
your app should run for a given request (hence the advisory usage of
return throughout these docs).
因此,当您使用 res.json({"foo":"dahoo"});
时,Sails 可能会将响应发送回客户端,关闭调用序列,如果它使用 Promises 或其他一些异步机制,可能会 "swallow" 进一步的代码,正如上述评论中所建议的那样。这可能是 Sails 中的内部编码,因此从外部无法立即看出为什么您的第二个代码块特别不起作用。
所以你应该坚持第一种模式:首先访问你的 属性,然后将 res.json()
放在控制器函数的末尾。
供参考:我终于解决了那个问题。
以某种方式隐藏在代码中,定义了进程退出处理程序:
process.on('exit', myErrorFunction.bind());
process.on('SIGINT', myErrorFunction.bind());
process.on('uncaughtException', myErrorFunction.bind());
问题是:这些行所在的函数被绑定到一个 cronjob。因此,每次执行 cronjob 时,都会注册新的处理程序。因此,我上面的假设(响应之前与响应之后)是错误的:事实上,在第一次执行 cronjob 之前一切正常。从那时起,它没有。最终,警告被触发(正确!)。
如果没有这个答案,我永远不会知道:
您必须添加一行代码才能获取堆栈跟踪:
process.on('warning', e => console.warn(e.stack));
此外,说到堆栈跟踪:在 Sails serverError 响应 (api/api/responses/serverError.js) 中,这样访问它很方便:
module.exports = function serverError (data, options) {
console.log(data.stack);
/* ... */
};
在基于 NodeJS 6.10.2/SailsJS 0.12.13 的 JavaScript 应用程序中,几个月以来我遇到了一种奇怪的错误行为。
在 Sails 控制器中,我尝试检索文字对象的 属性:
console.log(someObject.someProperty);
console.log("I am still here!");
但是,在我的例子中 someObject
是未定义的。所以,我希望得到像 'Cannot read property someProperty of undefined.' 这样的错误 - 然后 Node.js 完全停止或代码继续(下一个 console.log
)。
相反,代码只是在那一点停止执行,我收到一个奇怪的警告:“(节点:4822)警告:检测到可能的 EventEmitter 内存泄漏。添加了 11 个关闭的侦听器。使用 emitter.setMaxListeners() 来增加上限。”但是,无法预测此错误发生的频率。有的只有一次,有的大约有 20 次。
我发现的是,它与是否已经有回复的问题有某种联系。考虑以下因素:
mySailsControllerFunction: function(req, res) {
console.log(someObject.someProperty);
console.log("I am still here!");
res.json({"foo":"dahoo"});
}
这将导致 Sending 500 ("Server Error") response: ReferenceError: someObject is not defined
- 正是我所期望的。
但是,现在我先发送一些响应,然后尝试访问我不存在的 属性,将代码变成:
mySailsControllerFunction: function(req, res) {
res.json({"foo":"dahoo"});
setTimeout(function () {
console.log("Yeah!");
console.log(someObject.someProperty);
console.log("I am still here!");
},1000);
}
然后我经常什么也得不到: 'Yeah!' 显示,但之后什么也没有。事件侦听器错误有时存在,有时不存在。很奇怪。
此外,奇怪的是,这个问题似乎与自 Sails 开始以来所经过的时间有某种联系。我将您在上面看到的代码放在 Sails 控制器函数中,该函数在客户端重新连接后立即调用。然后我尝试调整超时值,多次重启 Sails 服务器。结果:如果我将超时设置为 1 秒,则在 5 次测试中的 4 次中,我将获得正确的错误行为。持续 10 秒大约为 50%,持续 30 秒错误将始终被忽略,没有任何控制台输出。
但是,如果我将我的测试代码放在 Sails 控制器之外,我总是会通过 Node.js 获得正确的错误行为。所以,我很确定这是 Sails 的错误行为,而不是 Node。
免责声明:我不了解 Sails。所以这可能相关也可能不相关,但我的回答可能会提供一些线索。
来自 Sails 文档: http://sailsjs.com/documentation/reference/response-res/res-json
This method is terminal, meaning it is generally the last line of code your app should run for a given request (hence the advisory usage of return throughout these docs).
因此,当您使用 res.json({"foo":"dahoo"});
时,Sails 可能会将响应发送回客户端,关闭调用序列,如果它使用 Promises 或其他一些异步机制,可能会 "swallow" 进一步的代码,正如上述评论中所建议的那样。这可能是 Sails 中的内部编码,因此从外部无法立即看出为什么您的第二个代码块特别不起作用。
所以你应该坚持第一种模式:首先访问你的 属性,然后将 res.json()
放在控制器函数的末尾。
供参考:我终于解决了那个问题。 以某种方式隐藏在代码中,定义了进程退出处理程序:
process.on('exit', myErrorFunction.bind());
process.on('SIGINT', myErrorFunction.bind());
process.on('uncaughtException', myErrorFunction.bind());
问题是:这些行所在的函数被绑定到一个 cronjob。因此,每次执行 cronjob 时,都会注册新的处理程序。因此,我上面的假设(响应之前与响应之后)是错误的:事实上,在第一次执行 cronjob 之前一切正常。从那时起,它没有。最终,警告被触发(正确!)。
如果没有这个答案,我永远不会知道:
process.on('warning', e => console.warn(e.stack));
此外,说到堆栈跟踪:在 Sails serverError 响应 (api/api/responses/serverError.js) 中,这样访问它很方便:
module.exports = function serverError (data, options) {
console.log(data.stack);
/* ... */
};