断点需打在可执行的同步逻辑行才生效;setTimeout回调内断点不生效常因source map未启用或断点位置错误;Promise链调试应逐个.then()首行设断点或用debugger语句;async/await中勿在await行打断点,而应在后续实际语句处设置。

断点打在回调函数内部才有效,外层声明行、未触发的异步分支、或被优化掉的代码行上加断点,VSCode 会显示空心红点,实际不会暂停。
为什么 setTimeout 回调里断点不生效?
常见现象是:在 setTimeout(() => { console.log('here'); }, 1000) 的箭头函数内部打了断点,但执行时直接跳过,调试器没停住。
- 检查是否启用了 source map:若项目经 Webpack/Vite 构建,
launch.json中必须设"sourceMaps": true,且构建产物目录下存在.js.map文件 - 确认断点位置在“可执行同步逻辑行”:
console.log('here')这一行可以,但setTimeout调用那一行(声明侧)不能打断点 - 避免在未进入的分支里设断点:比如
if (false) { debugger; }或 Promise 链中被catch吞掉错误后未走到的then分支
Promise 链式调用中如何逐层调试?
直接在每个 .then() 回调函数体第一行加断点最可靠;靠悬停看 res 值容易截断或显示 [object Promise]。
- 在 WATCH 面板手动添加表达式,例如:
JSON.stringify(res, null, 2)或res?.data?.items?.length - 不要依赖调用栈自动展开:Promise 异步微任务会脱离原始调用上下文,
CALL STACK里可能只显示promiseReactionJob,找不到你写的函数名 - 若想确认某次
then是否执行,可在其回调开头加debugger语句——它比 UI 断点更稳定,尤其在热更新或 HMR 场景下
async/await 函数里断点“跳过”怎么办?
这是最易误判的情况:看着光标进了 await fetch(...) 下一行,但断点没停,其实是 await 后续代码被编译成 Promise 状态机,原始行号映射失效。
- 确保
tsconfig.json或构建配置中"sourceMap": true且"inlineSources": true(尤其 TypeScript 项目) - 不要在
await行本身打断点——它不是可执行语句,而是语法糖;断点应放在await后的第一条实际语句,如const data = await api.get();的const data = ...这整行 - 如果用了
try/catch,记得在catch块内也设断点:错误可能被上层吞掉,导致你以为没进 catch,其实进了但没停住
真正难调试的从来不是嵌套多深,而是你默认“它应该执行”,结果发现那层回调压根没注册成功、没绑定事件、或被条件提前 return 掉了——先去 CALL STACK 看当前帧在哪,再顺藤摸到入口,比盲目加断点快得多。


















