我试图了解如何调试基于promises的异步代码。 By Promises我的意思是基于ECMAScript 6的承诺,通过调试我的意思是使用内置的chrome或firefox调试器。
我遇到的问题是 - 当发生错误时,无论我如何拒绝它,我都无法获得堆栈跟踪。
我试过这些:
console.log(new Error('Error occured'));
throw new Error('Throwing an Error');
return new Error('Error returned by the onRejected function');
reject(new Error('Pass Error to the reject function'));
但是这些都没有返回代码中的实际错误或堆栈跟踪。
所以我的问题是 - 如何正确调试javascript Promises?
答案 0 :(得分:58)
这是一个很好讨论的话题,令人遗憾的是,这实际上很难与原生承诺相提并论。
调试Chrome中的原始ES6承诺非常糟糕。这是因为他们会默默地抑制错误,每当你忽略一个捕获时,它都不会给你任何迹象表明承诺失败。更新:Chrome现在记录未处理的拒绝(see this link for how)
Promise.resolve("foo").then(function(){
throw new Error("You will never see this");// silent failure
});
在Firefox中,由于它们执行未处理的拒绝检测,事情会好一些 - 但是,它仍然很有趣,如果您在任何地方分配了承诺,它将无效。
包括Bluebird - 它是ES6承诺的超集,你可以在里面交换它,它有一个更丰富的API,它更快,它有惊人的堆栈跟踪。它是在考虑调试的基础上构建的,包括很好的错误处理功能。
一旦你加入Bluebird,请致电:
Promise.longStackTraces();
这会慢一点(它仍然会非常快)并会给你惊人的错误信息。例如:
Promise.resolve().then(function outer() {
return Promise.resolve().then(function inner() {
return Promise.resolve().then(function evenMoreInner() {
a.b.c.d()
});
});
});
在本机承诺中 - 这将是一个无声的失败,并且将很难调试 - 使用Bluebird承诺,这将在您的控制台中显示一个大的红色错误,默认情况下为您提供:
ReferenceError: a is not defined
at evenMoreInner (<anonymous>:6:13)
From previous event:
at inner (<anonymous>:5:24)
From previous event:
at outer (<anonymous>:4:20)
From previous event:
at <anonymous>:3:9
at Object.InjectedScript._evaluateOn (<anonymous>:581:39)
at Object.InjectedScript._evaluateAndWrap (<anonymous>:540:52)
at Object.InjectedScript.evaluate (<anonymous>:459:21)
完成调试后 - 您可以将其换出并回到本机承诺。我个人认为我知道自己在制作中有错误所以我不推荐它,但它肯定是可行的。
答案 1 :(得分:13)
*这不能直接回答你的问题,但它可能会有所帮助。
Chrome devtools最近推出了一项新功能,可用于调试异步代码,例如Promises。
http://www.html5rocks.com/en/tutorials/developertools/async-call-stack/
基本上,在“来源”标签中启用“异步”复选框,Chrome会为您重建调用堆栈,就好像它是同步代码一样。
答案 2 :(得分:12)
这个答案是Benjamin Gruenbaum答案的补充: 如果在promise链中使用catch语句,您将通过 error.stack 获得堆栈跟踪:
Promise.longStackTraces();
function outer() {
return Promise.resolve();
}
function inner() {
return Promise.resolve();
}
function evenMoreInner() {
a.b.c.d()
}
Promise.resolve()
.then(outer)
.then(inner)
.then(evenMoreInner())
.catch(function (err) {
console.log(err.message);
console.log(err.stack);
});
错误讯息:
ReferenceError: a is not defined
at evenMoreInner (test/test_promise.js:58:17) <<<< HERE's the error!
at Context.<anonymous> (test/test_promise.js:64:23)
答案 3 :(得分:1)
他们似乎正在使用Chrome中的调试工具。有关详细信息,请参阅此主题。
https://code.google.com/p/v8/issues/detail?id=3093
我已经检查过它是否已经在开发版或测试版中,但我希望它很快就会出现。它可能会在2015年1月左右包含在正常版本中(只是个人猜测,绝对没有承诺,因为我甚至不能为Google工作)。
答案 4 :(得分:0)
调试承诺的最佳方法是收听unhandledRejection
的{{1}}事件。
例如,以下是如何设置它并转储堆栈跟踪...
process
答案 5 :(得分:0)
您可以在Promise对象的.then()函数中添加console.log()语句: 如果需要,您还可以添加.catch()。
genericDbCaller(dbName, collectionName, dbFunctionName, params) {
return new Promise((resolve, reject) => {
DatabaseContext.instance.getDbConn(dbName)
.then((dbConn) => {
dbConn.get(collectionName)[dbFunctionName].apply(null, params)
.then(
(docs) =>{
----->>> console.log(docs);
resolve(docs);
})
.catch((e)=>{