try / catch导致堆栈中的<anonymous>

时间:2018-03-28 16:57:41

标签: javascript node.js v8

如果我的一个电话中有一个try/catch,它会导致堆栈重置&#34;重置&#34;在那时候。我有两个问题 -

1)为什么会这样?我想象一下v8引擎是如何工作的,但知道原因会很有趣。

2)有没有一个很好的解决方案来使用async/await并仍然保持整个堆栈跟踪?现在我在函数调用链中一直放置try/catch并将错误一直滚动到一个新的错误中(使用VError)。

以下代码给出了我期望的堆栈跟踪

async function one() {
  throw new Error("blah");
}

async function two() {
  await one();
}

async function three() {
  await two();
}

async function four() {
  try {
    await three();
  } catch (e) {
    console.log(e);
  }
}

four();

堆栈跟踪

Error: blah
  at one (/dev/async-stack/correct-stack.js:2:9)
  at two (/dev/async-stack/correct-stack.js:6:9)
  at three (/dev/async-stack/correct-stack.js:10:9)
  at four (/dev/async-stack/correct-stack.js:15:11)
  at Object.<anonymous> (/dev/async-stack/correct-stack.js:21:1)
  at Module._compile (module.js:652:30)
  at Object.Module._extensions..js (module.js:663:10)
  at Module.load (module.js:565:32)
  at tryModuleLoad (module.js:505:12)
  at Function.Module._load (module.js:497:3)

在中间插入try/catch会导致堆栈跟踪从最后try/catch开始。

async function one() {
  throw new Error("blah");
}

async function breaker() {
  return true;
}

async function stack() {
  try {
    await breaker();
  } catch (error) {
    throw error;
  }
}

async function two() {
  await stack(); // <-- this call 
  await one();
}

async function three() {
  await two();
}

async function four() {
  try {
    await three();
  } catch (e) {
    console.log(e);
  }
}

four();

堆栈跟踪

Error: blah
  at one (/dev/async-stack/broken-stack.js:2:9)
  at two (/dev/async-stack/broken-stack.js:19:9)
  at <anonymous>
  at process._tickCallback (internal/process/next_tick.js:188:7)
  at Function.Module.runMain (module.js:695:11)
  at startup (bootstrap_node.js:188:16)
  at bootstrap_node.js:609:3

1 个答案:

答案 0 :(得分:3)

async / await语法是如何解决的。对于您的第一个片段,它就像 1

function one() {
  return Promise.reject(new Error("blah"));
}

function two() {
  return one().then(() => {});
}

function three() {
  return two().then(() => {});
}

function four() {
  return three().then(() => {}).catch(e => { console.log(e); });
}

four();

而你的第二个片段就像 1

function one() {
  return Promise.reject(new Error("blah"));
}

function breaker() {
  return Promise.resolve(true);
}

function stack() {
  return breaker().then(() => {}).catch(error => { throw error; });
}

function two() {
  return stack().then(() => {
//                    ^^^^^^^ this anonymous function
    return one().then(() => {});
  })
}

function three() {
  return two().then(() => {});
}

function four() {
  return three().then(() => {}).catch(e => { console.log(e); });
}

four();

正如您所看到的,one()确实是从匿名then回调内部调用的。它实际上与您的标题建议的try / catch没有任何关系,而是在await调用之前任何one()

1:忽略Promise构造函数调用之类的细节,这些细节可能在内部使用延迟模式,因此它们不会显示在堆栈跟踪中。  更迂腐的方式是写function() { var _resolve, _reject, _promise = new Promise((res, rej) => { _resolve = res; _reject = rej; }); try { /* function body */ _resolve(_return_value); } catch(e) { _reject(e); } return _promise; }