在基于NodeJS 6.10.2 / SailsJS 0.12.13的JavaScript应用程序中,我经历了几个月的奇怪错误行为。
在Sails控制器中,我尝试检索文字对象的属性:
console.log(someObject.someProperty);
console.log("I am still here!");
但是,在我的情况下,someObject
未定义。因此,我希望得到一个错误,例如'无法读取某些属性未定义的属性。' - 然后Node.js完全停止或代码继续(使用下一个console.log
)。
相反,代码只是在那时停止执行,我收到一个奇怪的警告:"(node: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);
}
然后我经常一无所获:'是的!'显示,但之后什么都没有。有时会出现事件侦听器错误,有时不会出现错误。很奇怪。
另外,奇怪的是,问题似乎与Sails开始以来的时间有关。我将上面看到的代码放在Sails控制器函数中,该函数在客户端重新连接后立即调用。然后我玩了超时值,多次重启Sails服务器。结果:如果我将超时设置为1s,在5次测试中的4次中,我将得到正确的错误行为。对于10秒,它大约是50%,对于30秒,在没有任何控制台输出的情况下总是会忽略错误。
但是,如果我将测试代码放在Sails控制器之外,我总是会得到Node的正确错误行为。所以,我很确定这是Sails的错误行为,而不是Node。
答案 0 :(得分:2)
免责声明:我不知道Sails。所以它可能相关,也可能不相关,但我的回答可能提供线索。
从Sails文档中: http://sailsjs.com/documentation/reference/response-res/res-json
此方法是终端,这意味着它通常是最后一行代码 你的应用程序应该针对给定的请求运行(因此建议使用 返回这些文档)。
因此,当你使用res.json({"foo":"dahoo"});
时,Sails可能会将响应发送回客户端,关闭调用序列,如果它使用Promises或其他一些异步机制,可能会“吞下”更多的代码,正如上述评论中所述。这可能是Sails中的内部编码,所以从外面看并不是很明显为什么你的第二个代码块特别不起作用。
所以你应该坚持第一种模式:首先访问你的属性,然后将res.json()
放在控制器函数的末尾。
答案 1 :(得分:0)
供参考:我终于解决了这个问题。 在某种程度上隐藏在代码中,处理定义的退出处理程序:
process.on('exit', myErrorFunction.bind());
process.on('SIGINT', myErrorFunction.bind());
process.on('uncaughtException', myErrorFunction.bind());
问题是:这些行所在的功能与cronjob绑定。因此,每次执行cronjob时,都会注册新的处理程序。因此,我上面的假设(在响应之前和之后)是错误的:实际上一切都工作直到cronjob第一次被执行。从那时起,它没有。最终,警告被解雇了(正确!)。
如果没有这个答案,我绝不会发现:Make node show stack trace after EventEmitter warning 您必须添加一行代码才能获得堆栈跟踪:
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);
/* ... */
};