Bluebird(或其他 Promise 库)保留 Promise 错误堆栈跟踪
Bluebird (or other Promise library) Keep Promise Error Stack Traces
好吧,我可能只是漏掉了显而易见的东西,但我似乎找不到这个问题的一般答案,我的 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
实例继承的对象实例。
JavaScript 中的错误会在创建时捕获它们的跟踪,因此每当您重新抛出错误时,它都会自动捕获堆栈跟踪。
但是你并没有抛出错误。出于这个原因,bluebird 给你一个警告(是的)。如果您坚持抛出非错误而不是正确地子类化错误 - 您将需要通过手动捕获对象来手动欺骗该对象以获得正确的堆栈跟踪。通过在构造函数中创建一个 new Error
并将 .stack
设置到它的堆栈(可能必须做一些解析)或通过调用一个特定的方法:
function RejectWithAnError() {
var err = {error: true, message: "an error occurred"};
// err.__proto__ = new Error(); -- this is how you'd do it with prototypes btw
// explicitly capture the stack trace of the object
if(Error.captureStackTrace) Error.captureStackTrace(err);
}
Fiddle here. Just a note, .prototype
is a property used by functions to indicate the prototype of objects created by calling the function as a constructor. In order to set the prototype of an object directly you'd call __proto__
although that's rarely a particularly good idea. Here's an example with __proto__
instead of Error.captureStackTrace.
Promise.config({
warnings: false
});
好吧,我可能只是漏掉了显而易见的东西,但我似乎找不到这个问题的一般答案,我的 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
实例继承的对象实例。
JavaScript 中的错误会在创建时捕获它们的跟踪,因此每当您重新抛出错误时,它都会自动捕获堆栈跟踪。
但是你并没有抛出错误。出于这个原因,bluebird 给你一个警告(是的)。如果您坚持抛出非错误而不是正确地子类化错误 - 您将需要通过手动捕获对象来手动欺骗该对象以获得正确的堆栈跟踪。通过在构造函数中创建一个 new Error
并将 .stack
设置到它的堆栈(可能必须做一些解析)或通过调用一个特定的方法:
function RejectWithAnError() {
var err = {error: true, message: "an error occurred"};
// err.__proto__ = new Error(); -- this is how you'd do it with prototypes btw
// explicitly capture the stack trace of the object
if(Error.captureStackTrace) Error.captureStackTrace(err);
}
Fiddle here. Just a note, .prototype
is a property used by functions to indicate the prototype of objects created by calling the function as a constructor. In order to set the prototype of an object directly you'd call __proto__
although that's rarely a particularly good idea. Here's an example with __proto__
instead of Error.captureStackTrace.
Promise.config({
warnings: false
});