在vscode中调试Promise调用堆栈

时间:2017-06-02 23:46:17

标签: javascript node.js visual-studio-code es6-promise

在vscode中调试nodeJS Promises时有没有办法获取调用堆栈?我看到this GitHub issue支持异步调用堆栈,但看起来它与vanilla JS回调有关。

现在,当我在断点处暂停时,调用堆栈很小,即使我知道这个函数是从另一个(几个)函数调用的。

我在节点v6.9.x上运行

debug break no stack

编辑:将using属性添加到launch.json配置会添加更多堆栈框架,但它不是很有帮助:debug break next tick

我的所有函数都返回promises,屏幕截图中的函数被称为"protocol": "inspector"调用中的函数之一。

1 个答案:

答案 0 :(得分:2)

首先,如图所示的调用堆栈是正确的,因为这些是实际在堆栈上的函数。当围绕异步回调创建 Promise 并附加 .then 处理程序时,同步执行结束并且调用堆栈被解包。当回调在某个时间回调时,它会解析 Promise 并执行 .then 处理程序。此时,调用堆栈仅包含传递给 .then 的函数。

现在在很多情况下,Promise 链是扁平的,并且与创建时相反:

function a() {
   return Promise.resolve(1).then(it => it + 1); // 1
}

function b() {
   return a().then(it => it + 1); // 2
}

在上面第一个 .then 回调 (1) 执行时,唯一附加的回调是 (2),因此引擎可以生成“异步堆栈跟踪”,显示 Promise 链在哪些函数处继续。

现在对于普通的 Promise 来说,解析这些链只是为了生成一个堆栈跟踪是很多开销,但是对于 async functionawait Promise 来说,它非常简单。因此,从 NodeJS v12(以及现代浏览器)开始,如果你像这样编写上面的代码:

async function a() {
  const result = (await 1);
  _log_stack();
  return result + 1;
}

async function b() {
  return (await a()) + 1;
}
     
b();
     
function _log_stack() { console.log((new Error()).stack); }

然后您的调试器将显示正确的异步堆栈跟踪(如上所述生成)。您可以找到更深入的解释 here