在Node.js中使用async-await时,为什么会丢失堆栈跟踪?

问题描述 投票:1回答:1

当我运行以下程序时

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>

我想了解为什么在第二种情况下堆栈跟踪丢失但在第一种情况下没有丢失。

javascript node.js error-handling async-await stack-trace
1个回答
2
投票

因为在第一个代码中,直到Error的所有内容都与事件循环相同。

在异步回调之前,来自setTimeout的回调可以进入调用堆栈(堆栈跟踪是从它构建的),调用堆栈必须为空。

因此,由于第一个代码在Error调用之前运行所有同步,所有这些调用都在调用堆栈中。但是在第二种方法中,Error被称为awaiting setTimeout电话。当setTimeout完成。事件循环将回调放回堆栈,为此,调用堆栈必须为空。

所以现在,你在调用堆栈上没有functionTwofunctionThree,这就是为什么它们没有出现。

堆栈跟踪是发生错误时堆栈的状态。

以下是两个代码中堆栈发生情况的粗略解释:

第一码

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


在newests版本的Node.js上,您可以使用--async-stack-traces标志在使用异步代码时获得改进的堆栈跟踪。

您可以在https://v8.dev/blog/fast-async上阅读更多相关内容

© www.soinside.com 2019 - 2024. All rights reserved.