关键在于启用异步堆栈追踪(--async-stack-traces)、在await行或.then回调首行精准设断点,并结合调用栈与Scope面板验证Promise状态,否则await后续逻辑跳过、.then断点失效、错误堆栈不显业务路径。

VSCode 调试 Node.js 异步代码,关键不在“能不能断点”,而在于“断点停在哪、调用栈看不看得清、Promise 状态查不查得准”——默认配置下,await 后续逻辑常跳过、Promise.then 里断点失效、错误堆栈只显示 internal 而非业务路径,这三类问题占实际调试阻塞的 80% 以上。
启用异步堆栈追踪(--async-stack-traces 必加)
Node.js v12+ 默认不展开 Promise 链中的原始调用位置,导致你在 .catch 里看到的错误堆栈,顶层是 nextTick 或 Promise.then,根本找不到 await fetch('/api') 是哪一行抛的错。
必须在 launch.json 的 runtimeArgs 中显式加入该标志:
{
"type": "node",
"request": "launch",
"name": "Debug Async",
"program": "${workspaceFolder}/index.js",
"runtimeArgs": [
"--async-stack-traces",
"--enable-source-maps"
],
"skipFiles": ["<node_internals>/**"]
}
-
--async-stack-traces是核心,没它就等于放弃异步上下文 -
--enable-source-maps必须配套,否则 TypeScript 或打包后代码无法定位源码行 - 不要依赖 VSCode UI 里的“Async stack traces”开关——那个只影响部分视图,不改底层行为
await 行设断点 ≠ 暂停在 resolve 时刻
在 const data = await fetch(url) 这行打个断点,VSCode 实际会在 await 表达式求值开始时暂停(即进入 microtask 队列前),而不是等 fetch 返回后。你看到的 data 还是 undefined,容易误判执行进度。
真正要观察返回值,应该:
使用一条命令部署ProbeChain Rydberg测试网代理节点。自动注册为Agent(NodeType=1),免gas,支持macOS/Linux/Windows。触发词:/r
- 断点打在
await下一行(如console.log(data)),这时data已赋值 - 或在
await行使用“单步进入(F11)”,VSCode 会跳进 runtime 的 Promise 处理逻辑,不推荐——信息噪音大 - 更稳的方式:在
await行右侧空白处右键 → “Add Conditional Breakpoint”,填!data,确保只在未赋值时停
调试 Promise.then() 和 Promise.catch() 的陷阱
直接在 .then(res => { ... }) 的花括号内第一行设断点,大概率不触发——因为 V8 会把简单 then 回调内联优化,断点被跳过。
可靠做法是:
- 把回调写成命名函数:
promise.then(handleSuccess).catch(handleError),再在handleSuccess函数首行打断点 - 或在回调内部第一行加
debugger语句,强制中断(注意:仅限开发环境,勿提交) - 对未捕获异常,务必在调试面板勾选
Uncaught Exceptions,否则Promise.reject()会直接退出,断点无效 - 避免在
.then链中混用await和.then,比如await p.then(...),这种写法会让调试器混淆执行阶段
热重载调试时断点丢失(nodemon --inspect-brk 配置要点)
用 nodemon 启动时,VSCode 默认的 launch 模式会失败——因为 nodemon 启动的是子进程,不是直接运行 node。
正确配置分两步:
- 在
launch.json中改用"request": "attach"模式,并指定端口(nodemon默认用9229) -
package.json里写清楚启动命令:"debug": "nodemon --inspect-brk=9229 index.js" -
launch.json示例:
{
"type": "node",
"request": "attach",
"name": "Attach to nodemon",
"port": 9229,
"address": "localhost",
"localRoot": "${workspaceFolder}",
"remoteRoot": "${workspaceFolder}"
}
注意:--inspect-brk 让进程启动即暂停,确保 VSCode 连上后再开始执行,断点不会漏掉入口逻辑;若用 --inspect,可能因连接延迟错过初始化阶段。


















