JS宏任务与微任务实战通过带序号日志、console.group分组、DOM渲染观察及可交互步进调试,可视化事件循环执行顺序,覆盖宏中Promise、微中setTimeout、微中queueMicrotask三类嵌套场景。

JS 中宏任务与微任务的实战演练,核心是通过可观察、可调试的代码结构,把事件循环的执行顺序“可视化”出来。不需要复杂框架,一个带计时标记和 console.group 的 HTML 页面就能搞定。
用带序号的日志清晰呈现执行顺序
每次任务执行都打印带编号和类型(macro / micro)的日志,并用 console.group() 分组展开,方便逐轮对比。关键不是“写对”,而是“看出错在哪”。
- 所有宏任务入口统一加序号,如
setTimeout(() => { log('macro-1') }, 0) - 微任务统一用
Promise.resolve().then(() => log('micro-1'))或queueMicrotask - 在日志中显式标注当前调用栈深度或轮次,例如 “【第1轮宏任务】→ macro-1”
构造典型嵌套触发链验证规则
真实项目里常出现“宏任务里 new Promise → then 里又 setTimeout”,这种嵌套最易混淆。实战项目应包含至少三类嵌套:
- 宏任务中创建 Promise 并链式调用 then/catch —— 微任务立即入队
- 微任务中调用
setTimeout或setInterval—— 新宏任务排到下一轮末尾 - 微任务中再调用
queueMicrotask—— 新微任务插在当前轮末尾,但仍在本轮内
加入 DOM 渲染观察强化理解
仅靠 console 日志不够直观。添加一个实时更新的 区域,每次日志同时追加到页面,并在关键节点调用 getComputedStyle 强制触发重排,确认浏览器是否已渲染上一轮结果。
- 例如:在第一个宏任务末尾插入
document.body.offsetHeight,可让浏览器同步刷新视图 - 配合
requestAnimationFrame(属于宏任务)对比其执行时机,验证它与 setTimeout(0) 的差异
设计可交互的“暂停/步进”调试模式
用按钮控制任务节奏,比如“执行下一轮宏任务”、“清空微任务队列并继续”,帮助学习者主动拆解流程。
- 用数组模拟任务队列,不直接依赖原生 API,便于拦截和日志注入
- 每个任务包装为对象:
{ type: 'macro', fn: () => {}, label: 'timeout-2' } - 点击按钮时手动出队、执行、记录,再自动调度下一轮——真正看清“谁在什么时候被谁推入”











