尝试在 nodejs 上的异步承诺链上使用未定义变量时,控制台或日志中没有未捕获的异常

no uncaughtException in console or logs when attempting to use an undefined variable on asynchronous promise chain on nodejs

我注意到一些非常奇怪的事情:

在异步承诺链上,当我错误地尝试记录一个不存在的变量时,它创建了一个我在控制台中看不到的异常。

当我以同步方式调用完全相同的函数时(直接从方法调用它,而不是作为已解决的承诺链的结果异步激活它)它显示了预期的错误(参见下面的堆栈跟踪异常) .

这让我抓狂,因为 promise 链激活了方法(我可以看到它开始通过我在其开头添加的日志行做事),但随后它到达了有问题的日志行,从而停止了整个方法从实现其目标,但没有打印错误,也没有看到堆栈跟踪。

这使得整个调试问题变得相当复杂,我确定我在这里做错了什么。但它是什么?

这是我使用的代码:(我标记了写得不好的变量)

module.exports = {
  sync: function(){
      console.log(doesNotExist); // error logs
  }, 
  async: function(){
      Q().then(function(){ // actually from an API returning a promise
        console.log(doesNotExist); // no error in log or `unhandledException` process event
      });
  }
};

更新: 使用本杰明的解决方案后

process.on("unhandledRejection", function(r, e){
console.log("Oh No! Unhandled rejection!! \nr::", r,"\ne::", e);
});

情况好多了。现在我得到一些日志打印,看起来像这样

Oh No! Unhandled rejection!!
r:: [ReferenceError: Resolved123PasswordHash is not defined]
e:: { state: 'rejected',reason: [ReferenceError: Resolved123PasswordHash is not defined] }

但我仍然没有像在同步方法调用中那样得到实际的堆栈跟踪。

这是我在没有承诺链的情况下直接调用方法时的样子:

2015-07-05T18:22:51.405Z :: [ error ] :: uncaughtException: Resolved123PasswordHash is not defined["ReferenceError: Resolved123PasswordHash is not defined",
"    at addUserAfterHashResolved (I:\iBitch\services\userServices.js:19:77)",
"    at Object.module.exports.addUser (I:\iBitch\services\userServices.js:22:3)",
"    at Object.<anonymous> (I:\iBitch\ikuter.js:263:14)",
"    at Module._compile (module.js:460:26)",
"    at Object.Module._extensions..js (module.js:478:10)",
"    at Module.load (module.js:355:32)",
"    at Function.Module._load (module.js:310:12)",
"    at Function.Module.runMain (module.js:501:10)",
"    at startup (node.js:129:16)",
"    at node.js:814:3"]

是否有可能在使用异步承诺时获得完整的堆栈跟踪?

因为错误消息很好,但它仍然没有将我定向到特定的代码行,所以我可以知道我应该修复什么。

又一次编辑:: 我发现如果我在承诺链的末尾使用“.done()”,它会显示堆栈跟踪,但随后它会使整个应用程序崩溃(这也是不受欢迎的行为) 也许这就是我需要采取的方向,但稍微修改一下? 我知道如果我开始将每个承诺链放在 try/catch 下,它将严重影响性能,所以显然不是这里的补充解决方案...

无论如何,我们将提供任何进一步的帮助。

假设您使用的是 Q 1.3+,您正在寻找 unhandledRejection 而不是 uncaughtException:

process.on("unhandledRejection", function(r, e){
    console.log("Oh No! Unhandled rejection!!", r, e);
});

在 1.3 之前,Q 中不存在此功能。其他库(如 bluebird)多年来一直内置此功能。

promise 以这种方式运行的原因是您将来可能仍会附加一个 .catch 处理程序来处理错误。流程事件假设如果你没有在事件循环中附加 .catch 轮流你永远不会(合理的 IMO)。