不存在的属性:EventEmitter内存错误,而不是正确的错误消息

在基于NodeJS 6.10.2 / SailsJS 0.12.13的JavaScript应用程序中,我经历了几个月的奇怪的错误行为。

在Sails控制器中,我尝试检索字面对象的属性:

console.log(someObject.someProperty); console.log("I am still here!"); 

但是,在我的情况下someObject是未定义的。 所以,我希望得到一个错误,如'不能读取属性someProperty未定义。 – 然后Node.js完全停止或代码继续(与下一个console.log )。

相反,代码只是简单地停止执行在这一点,我得到了一个奇怪的警告:“(节点:4822)警告:可能的EventEmitter内存泄漏检测到11closures监听添加使用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服务器。 结果:如果我将超时设置为1秒,则在5次testing中的4次中,我将得到正确的错误行为。 10秒钟大概是50%,30秒后总是会忽略掉任何控制台输出。

但是,如果我将testing代码放在Sails控制器之外,则Node总是会得到正确的错误行为。 所以,我很确定这是Sails的错误行为,而不是Node。

免责声明:我不知道帆船。 所以它可能会或可能不会有关系,但我的答案可能会提供一个线索。

从Sails文档: http : //sailsjs.com/documentation/reference/response-res/res-json

这个方法是terminal的,这意味着它通常是你的应用程序应该为给定请求运行的代码的最后一行(因此在这些文档中对返回的咨询使用)。

因此,当你使用res.json({"foo":"dahoo"}); ,Sails可能会将响应发送回客户端,closures调用序列,如果使用Promise或其他asynchronous机制,则可能会“吞下”其他代码,如上面的评论中所build议的那样。 这可能是Sails中的内部编码,所以从外部不是很明显为什么你的第二个代码块特别不起作用。

所以你应该坚持第一种模式:首先访问你的财产,并把res.json()在控制器function的末尾。

供参考:我终于解决了这个问题。 有一些隐藏在代码中的进程退出处理程序:

  process.on('exit', myErrorFunction.bind()); process.on('SIGINT', myErrorFunction.bind()); process.on('uncaughtException', myErrorFunction.bind()); 

问题是:这些行所在的函数绑定到cronjob。 所以,每次执行cronjob,新的处理程序都被注册了。 所以,我上面的假设(之前和之后的回应)是错误的:事实上,一切工作,直到cronjob被执行的第一次。 从那时起,它没有。 最后,警告被解雇(正确!)。

我从来没有发现没有这个答案: 在EventEmitter警告后,使节点显示堆栈跟踪您必须添加一行代码来获取堆栈跟踪:

 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); /* ... */ };