如何在带有promise的setTimeout中看到完整的堆栈错误跟踪

时间:2021-10-07 20:15:53

I'm trying to understand how can I get a full stack trace from a promise rejection caused by a setTimeout

我试图了解如何从setTimeout引起的承诺拒绝中获得完整的堆栈跟踪

I'm running the following example:

我正在运行以下示例:

'use strict';

function main() {
  f1().catch(e => {
    console.error('got error with trace:');
    console.error(e);
  });

  f2().catch(e => {
    console.error('got error with trace:');
    console.error(e);
  });
}

async function f1() {
  return new Promise((resolve, reject) => {
    reject(new Error('Error in normal flow'));
  });
}

async function f2() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject(new Error('Error in timeout'));
    }, 0);
  });
}

main();

And I'm getting this output:

而且我得到了这个输出:

got error with trace:
Error: Error in normal flow
    at Promise (/Users/me/project/example.js:25:12)
    at Promise (<anonymous>)
    at f2 (/Users/me/project/example.js:24:10)
    at main (/Users/me/project/example.js:9:3)
    at Object.<anonymous> (/Users/me/project/example.js:29:1)
    at Module._compile (module.js:569:30)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:503:32)
    at tryModuleLoad (module.js:466:12)
    at Function.Module._load (module.js:458:3)
got error with trace:
Error: Error in timeout
    at Timeout.setTimeout [as _onTimeout] (/Users/me/project/example.js:18:14)
    at ontimeout (timers.js:488:11)
    at tryOnTimeout (timers.js:323:5)
    at Timer.listOnTimeout (timers.js:283:5)

How can I make make the stack trace of the promise that is initiated with setTimeout be more verbose like the promise without setTimeout?

如何使用setTimeout启动的承诺的堆栈跟踪更像是没有setTimeout的promise更详细?

When this happen to me in real production code, I can't know exactly where the error was initiated from. Which makes it very difficult to debug.

当在实际生产代码中发生这种情况时,我无法确切地知道错误的起源。这使得调试非常困难。

2 个解决方案

#1


0  

I've done something like the following before:

我之前做过类似的事情:

async function f2() {
  return new Promise((resolve, reject) => {
    const potentialError = new Error('Error in timeout');
    setTimeout(() => {
      reject(potentialError);
    }, 0);
  });
}

That'll result in an error just like the one outside setTimeout. Wherever you create your error, that'll dictate your stack trace.

这将导致错误,就像setTimeout之外的错误一样。无论您在何处创建错误,都将决定您的堆栈跟踪。

One use case for this for me has been a test that times out because a promise never resolves (in my case, with puppeteer and mocha/jasmine). Because the timeout had no meaningful stack trace, I wrote a wrapper around the promise that includes a setTimeout, much like this example.

对我来说,一个用例是一个超时的测试,因为承诺永远不会解决(在我的情况下,使用puppeteer和mocha / jasmine)。因为超时没有有意义的堆栈跟踪,所以我写了一个包含setTimeout的promise的包装器,就像这个例子一样。

#2


0  

I'd try to write it like this:

我试着这样写:

async function f() {
  await new Promise((resolve, reject) => {
    setTimeout(resolve, 0);
  });
  throw new Error('Error after timeout');
}

Try to avoid doing anything in non-promise callbacks.

尽量避免在非承诺回调中做任何事情。

#1


0  

I've done something like the following before:

我之前做过类似的事情:

async function f2() {
  return new Promise((resolve, reject) => {
    const potentialError = new Error('Error in timeout');
    setTimeout(() => {
      reject(potentialError);
    }, 0);
  });
}

That'll result in an error just like the one outside setTimeout. Wherever you create your error, that'll dictate your stack trace.

这将导致错误,就像setTimeout之外的错误一样。无论您在何处创建错误,都将决定您的堆栈跟踪。

One use case for this for me has been a test that times out because a promise never resolves (in my case, with puppeteer and mocha/jasmine). Because the timeout had no meaningful stack trace, I wrote a wrapper around the promise that includes a setTimeout, much like this example.

对我来说,一个用例是一个超时的测试,因为承诺永远不会解决(在我的情况下,使用puppeteer和mocha / jasmine)。因为超时没有有意义的堆栈跟踪,所以我写了一个包含setTimeout的promise的包装器,就像这个例子一样。

#2


0  

I'd try to write it like this:

我试着这样写:

async function f() {
  await new Promise((resolve, reject) => {
    setTimeout(resolve, 0);
  });
  throw new Error('Error after timeout');
}

Try to avoid doing anything in non-promise callbacks.

尽量避免在非承诺回调中做任何事情。