Promise.catch正在吞噬错误

时间:2016-03-14 18:59:59

标签: javascript node.js error-handling callback promise

我在Node.js中做了很多带有回调的异步编码和优秀的异步库,效果很好。我正在尝试使用一个使用promises的模块,但是我遇到了一个问题,即在promise之后抛出的任何错误仍然被冒充并被promise错误处理程序捕获。

这使得调试错误非常困难,因为我不知道它们会弹出的位置,也不会抛出它们,也不会使应用程序崩溃。

以下示例代码;我想要做的就是退出promise链并在解决后将其留下,而不是捕获与之无关的所有后续错误。

function one (input, callback) {

  doSomeAsyncWork(input)
  .then(function (result) {
    return callback(null, result);
  })
  .catch(function (err) {
    logError(err);
    return callback(err);
  });

}

function two (err, result) {

  if (err) { ... }

  var x = callAMethodThatThrows();
  ...

}

one('abc', two);

在此示例中,方法 callAMethodThatThrows()会抛出一个错误,该错误会冒泡到promise catch()块。这可以防止应用程序崩溃并使其处于未知状态。

非常感谢任何建议,谢谢。

2 个答案:

答案 0 :(得分:3)

是的,抱歉 - 我们正在修复(1)Node中的默认行为。与此同时,我推测并Petka添加了(在其他人的支持下)用于查找这些错误的钩子:

process.on("unhandledRejection", (err, p) => {
    console.error(err); // print the error
});

请注意,如果您本身异步执行.catch,这可能会产生一些误报 - 根据我的经验非常罕见。

另请注意,对于承诺,您的服务器通常处于未知状态,并且可以并且应该在有意义时尝试从错误中恢复。由于promises一直意味着抛出安全的代码,因此可以进行细粒度的错误处理。

请注意,promises使异步库很大程度上不需要。如果你仍然希望使用回调,只是希望"那些讨厌的承诺"会让你独自一人,让你继续写回调,这很好 - 承诺是安全的,但你可以通过执行 off 承诺代码来逃避:

myPromiseFn().then(v => {
    process.nextTick(() => cb(null, v)); // next tick, to escape the chain
}, e => process.nextTick(() => cb(e));

请注意,公平承诺库还带有asCallback回调,用于将promise代码转换为节点err-back回调。

(1)有些人声称没有问题,请参见图

答案 1 :(得分:1)

感谢Ben的回答,我发现可以使用诸如nodeify之类的模块将承诺转换为回调。这允许我们使用回调来保留所有代码,并避免错误被承诺吞噬。非常有用。