为什么在 Node.js 中使用 async-await 时会丢失堆栈跟踪?
Why do I lose stack trace when using async-await in Node.js?
当我运行下面的程序
async function functionOne() {
throw new Error('Error here prints the complete stack');
await new Promise((resolve) => {
setTimeout(() => { resolve(); }, 1000);
});
}
async function functionTwo() {
await functionOne();
}
async function functionThree() {
await functionTwo();
}
functionThree()
.catch((error) => {
console.error(error);
});
我得到以下输出,它通过各种调用的函数打印堆栈
Error: Error here prints the complete stack
at functionOne (/home/divyanshu/programming/errorHandlingAsyncAwait/index.js:3:9)
at functionTwo (/home/divyanshu/programming/errorHandlingAsyncAwait/index.js:11:9)
at functionThree (/home/divyanshu/programming/errorHandlingAsyncAwait/index.js:15:9)
at Object.<anonymous> (/home/divyanshu/programming/errorHandlingAsyncAwait/index.js:18:1)
at Module._compile (module.js:612:30)
at Object.Module._extensions..js (module.js:623:10)
at Module.load (module.js:531:32)
at tryModuleLoad (module.js:494:12)
at Function.Module._load (module.js:486:3)
at Function.Module.runMain (module.js:653:10)
但是当下面程序中的await调用后抛出错误时
async function functionOne() {
await new Promise((resolve) => {
setTimeout(() => { resolve(); }, 1000);
});
throw new Error('Error here prints incomplete stack');
}
async function functionTwo() {
await functionOne();
}
async function functionThree() {
await functionTwo();
}
functionThree()
.catch((error) => {
console.error(error);
});
这是输出
Error: Error here prints incomplete stack
at functionOne (/home/divyanshu/programming/errorHandlingAsyncAwait/index.js:7:9)
at <anonymous>
我想了解为什么堆栈跟踪在第二种情况下丢失,但在第一种情况下却没有。
因为在第一个代码中,Error
之前的所有内容都在事件循环的同一刻度上。
在setTimeout
的那个异步回调进入调用栈之前(栈跟踪是从它构建的),调用栈必须是空的。
因此,由于第一个代码在 Error
调用之前同步运行所有内容,因此所有这些调用都在调用堆栈中。但是在第二种方法中,Error
在 await
调用 setTimeout
之后被调用。 setTimeout
完成后。事件循环将回调放回堆栈,为此,调用堆栈必须为空。
所以现在,调用堆栈中没有 functionTwo
和 functionThree
,这就是它们没有出现的原因。
T堆栈跟踪是发生错误时堆栈的状态。
以下是对两个代码中堆栈发生的情况的粗略解释:
第一码
1) functionThree is pushed into the stack
2) functionTwo is pushed into the stack
3) functionOne is pushed into the stack
4) Error is thrown
二码
1) functionThree is pushed into the stack
2) functionTwo is pushed into the stack
3) functionOne is pushed into the stack
4) awat ...setTimeout is called
5) All 3 functions return a Promise
6) The stack is empty
... setTimeout ends
Next tick of the event loop
1) setTimeout callback is called
2) Error is thrown
我建议观看此视频以了解所有这些是如何工作的:
What the heck is the event loop anyway 菲利普·罗伯茨
在最新版本的 Node.js 上,您可以使用 --async-stack-traces
标志来改进处理异步代码时的堆栈跟踪。
阅读更多相关信息
当我运行下面的程序
async function functionOne() {
throw new Error('Error here prints the complete stack');
await new Promise((resolve) => {
setTimeout(() => { resolve(); }, 1000);
});
}
async function functionTwo() {
await functionOne();
}
async function functionThree() {
await functionTwo();
}
functionThree()
.catch((error) => {
console.error(error);
});
我得到以下输出,它通过各种调用的函数打印堆栈
Error: Error here prints the complete stack
at functionOne (/home/divyanshu/programming/errorHandlingAsyncAwait/index.js:3:9)
at functionTwo (/home/divyanshu/programming/errorHandlingAsyncAwait/index.js:11:9)
at functionThree (/home/divyanshu/programming/errorHandlingAsyncAwait/index.js:15:9)
at Object.<anonymous> (/home/divyanshu/programming/errorHandlingAsyncAwait/index.js:18:1)
at Module._compile (module.js:612:30)
at Object.Module._extensions..js (module.js:623:10)
at Module.load (module.js:531:32)
at tryModuleLoad (module.js:494:12)
at Function.Module._load (module.js:486:3)
at Function.Module.runMain (module.js:653:10)
但是当下面程序中的await调用后抛出错误时
async function functionOne() {
await new Promise((resolve) => {
setTimeout(() => { resolve(); }, 1000);
});
throw new Error('Error here prints incomplete stack');
}
async function functionTwo() {
await functionOne();
}
async function functionThree() {
await functionTwo();
}
functionThree()
.catch((error) => {
console.error(error);
});
这是输出
Error: Error here prints incomplete stack
at functionOne (/home/divyanshu/programming/errorHandlingAsyncAwait/index.js:7:9)
at <anonymous>
我想了解为什么堆栈跟踪在第二种情况下丢失,但在第一种情况下却没有。
因为在第一个代码中,Error
之前的所有内容都在事件循环的同一刻度上。
在setTimeout
的那个异步回调进入调用栈之前(栈跟踪是从它构建的),调用栈必须是空的。
因此,由于第一个代码在 Error
调用之前同步运行所有内容,因此所有这些调用都在调用堆栈中。但是在第二种方法中,Error
在 await
调用 setTimeout
之后被调用。 setTimeout
完成后。事件循环将回调放回堆栈,为此,调用堆栈必须为空。
所以现在,调用堆栈中没有 functionTwo
和 functionThree
,这就是它们没有出现的原因。
T堆栈跟踪是发生错误时堆栈的状态。
以下是对两个代码中堆栈发生的情况的粗略解释:
第一码
1) functionThree is pushed into the stack
2) functionTwo is pushed into the stack
3) functionOne is pushed into the stack
4) Error is thrown
二码
1) functionThree is pushed into the stack
2) functionTwo is pushed into the stack
3) functionOne is pushed into the stack
4) awat ...setTimeout is called
5) All 3 functions return a Promise
6) The stack is empty
... setTimeout ends
Next tick of the event loop
1) setTimeout callback is called
2) Error is thrown
我建议观看此视频以了解所有这些是如何工作的:
What the heck is the event loop anyway 菲利普·罗伯茨
在最新版本的 Node.js 上,您可以使用 --async-stack-traces
标志来改进处理异步代码时的堆栈跟踪。