【发布时间】:2016-05-14 10:38:31
【问题描述】:
好吧,我可能只是错过了显而易见的事情,但我似乎找不到这个问题的一般答案,而且我的 Google-Fu 到目前为止让我失望了。
在 Promise 的 Catch 处理程序中,如何重新抛出错误,同时仍保留原始错误的 Promise 堆栈跟踪?
这可能不是正确的描述,所以这里是一个例子:
https://jsfiddle.net/8sgj8x4L/19/
使用此代码,跟踪堆栈为:
Warning: a promise was rejected with a non-error: [object String]
at RejectWithAnError (https://fiddle.jshell.net/_display/:51:19)
at https://fiddle.jshell.net/_display/:57:14
From previous event:
at StartTheProgram (https://fiddle.jshell.net/_display/:56:6)
at window.onload (https://fiddle.jshell.net/_display/:67:1)
bluebird.js:1444 Unhandled rejection an error occurred
但是,如果添加了 catch 处理程序,并且从该处理程序重新拒绝或重新抛出错误,则堆栈将成为新的 Reject 方法调用的位置:
https://jsfiddle.net/8sgj8x4L/18/
哪个跟踪此堆栈跟踪:
Warning: a promise was rejected with a non-error: [object String]
at https://fiddle.jshell.net/_display/:65:23
From previous event:
at StartTheProgram (https://fiddle.jshell.net/_display/:61:11)
at window.onload (https://fiddle.jshell.net/_display/:70:1)
bluebird.js:1444 Unhandled rejection an error occurred
您可以看到调度原始错误“RejectWithAnError”的内部方法从第二个堆栈中消失,因为错误被捕获并重新抛出。
作为参考,这里是来自 JSFiddle 的完整代码(最新的 Bluebird 被引用为外部依赖项):
window.P.longStackTraces();
function RejectWithAnError() {
var err = {error: true, message: "an error occurred"};
err.prototype = new Error();
return window.P.reject(err);
}
function StartTheProgram() {
return RejectWithAnError()
// Comment out this catch handler completely, and the Promise stack trace will correctly show the "RejectWithAnError" method as the error origin.
.catch(function (status) {
console.log("[WARN] Catch handler was called.");
// Neither of these lines will show "RejectWithAnError" in the Promise chain stack trace.
// throw status;
return window.P.reject(status);
});
}
StartTheProgram()
(顺便说一句,这是我的第一个 Stack Overflow 问题,所以我希望这是这个问题的正确格式。)
编辑:更新示例以拒绝使用继承自新 Error 实例的对象实例。
【问题讨论】:
-
旁注:总是拒绝
Error构造函数的实例。 -
status是一个字符串,不能保存堆栈信息。这就是为什么您应该始终使用Error对象。 -
感谢您的指点。我已经更新了 JSFiddle 以使用错误实例:https://jsfiddle.net/8sgj8x4L/12/ 原始堆栈跟踪绝对有帮助,理想情况下,它会保留通过复杂的承诺链导致错误的承诺链。例如,在 Bluebird 中启用长堆栈跟踪时,您可以看到导致失败的所有承诺,但如果我添加一个 catch 处理程序,它似乎会在 Promise 中调用该 catch 处理程序之前丢失任何信息链。
标签: javascript stack promise try-catch bluebird