宏任务中抛出未捕获异常仅终止该宏任务后续执行,不影响其他宏任务和已入队微任务;异常冒泡至全局触发onerror,但不阻塞事件循环继续调度。

宏任务中抛出异常会终止当前宏任务,但不影响其他宏任务
在 JavaScript 事件循环中,每个宏任务(如 setTimeout 回调、click 事件处理函数、setInterval 回调)是独立执行单元。如果其中某一个宏任务内部抛出未捕获的异常,它只会中断自身后续代码的执行,不会波及正在排队或已入队的其他宏任务。
例如:
-
setTimeout(() => { throw new Error('A'); console.log('不会执行'); }, 0);—— 报错后console.log不执行,但不会阻止下一个setTimeout运行; - 连续注册两个定时器,第一个抛错,第二个仍会按计划触发并执行;
- 用户连续点击两个按钮,各自绑定的 click 回调互不干扰,一个报错不影响另一个运行。
异常会沿调用栈向上冒泡,直到被捕获或到达全局
宏任务中抛出的异常遵循标准的错误传播规则:从抛出处开始,逐层向外查找最近的 try-catch。若整个宏任务内无捕获,异常将冒泡至全局作用域。
浏览器环境中,这会导致:
立即学习“Java免费学习笔记(深入)”;
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 控制台输出错误堆栈;
- 触发
window.onerror或window.addEventListener('error'); - 若未监听,错误仅可见,不中断页面其他功能。
注意:它不会中断当前宏任务之外的同步代码(比如刚执行完的上一个宏任务中的同步逻辑),也不会影响微任务队列中已存在的 Promise 回调——这些微任务仍会在当前宏任务崩溃后照常执行。
微任务不受同级宏任务异常影响,但会受其执行时机约束
一个宏任务执行完毕后,引擎会立即清空微任务队列。这个“清空”动作本身是原子性的,与该宏任务是否成功无关。
也就是说:
- 即使宏任务里
throw了,只要微任务已在队列中(比如由前面的Promise.resolve().then(...)注册),它们仍会被执行; - 但如果异常发生在微任务注册之前(比如在
new Promise的 executor 中同步抛错),那么对应的.then就不会被加入微任务队列; - 微任务内部再抛错,同样只影响自己,不会拖垮外层宏任务的收尾流程(如 UI 渲染)。
推荐的容错实践
为避免单点异常导致功能断裂,建议在关键宏任务入口做兜底处理:
- 对第三方回调(如事件监听器、定时器)统一包裹
try-catch; - 使用
window.addEventListener('error', handler)捕获未处理异常并上报; - 避免在宏任务中依赖前序宏任务的副作用状态,保持任务间低耦合;
- 对异步链路(如 fetch → then → render)优先用 Promise 链式错误处理,而非依赖宏任务级 try-catch。

















