无需登录 数据私有 本地保存

JavaScript事件循环可视化 - 任务队列动画

38
0
0
0
同步任务 宏任务 (setTimeout) 微任务 (Promise) Web API等待中 正在执行
调用栈 Call Stack 0
栈为空,等待任务...
Event Loop
Web APIs 0
无等待中的异步操作
微任务队列 Microtask Queue 0
微任务队列为空
宏任务队列 Macrotask Queue 0
宏任务队列为空
手动添加任务到队列
添加后需重置场景或手动推进来观察效果
执行日志 Console 步骤: 0
🚀 工具就绪,请选择场景并开始执行...
常见问题 & 知识点 FAQ

JavaScript是单线程语言,一次只能执行一个任务。事件循环是JS运行时的核心机制,它不断检查调用栈是否为空,如果为空就从任务队列中取出任务执行。这使得JS能够非阻塞地处理异步操作。事件循环的完整流程:执行一个宏任务 → 清空所有微任务 → 渲染更新 → 重复。推荐使用我们的可视化工具逐步观察这一过程。

宏任务包括:setTimeoutsetIntervalsetImmediate(Node.js)、I/O操作、UI渲染等。每次事件循环只执行一个宏任务。
微任务包括:Promise.then/catch/finallyqueueMicrotaskMutationObserver等。每次事件循环会清空整个微任务队列(包括执行过程中新产生的微任务)。
这就是为什么Promise的回调通常比setTimeout先执行——微任务在每轮循环中优先被处理。

即使延迟设为0毫秒,setTimeout的回调也必须经过Web APIs注册 → 进入宏任务队列 → 等待当前调用栈清空且微任务队列清空后才能执行。浏览器还有最小延迟限制(嵌套层级超过5层时至少4ms)。在我们的工具中,延迟0的任务在Web APIs中停留1步后进入宏任务队列,您可以清晰看到它等待微任务先执行完毕。

调用栈是LIFO(后进先出)的数据结构,用于跟踪函数调用。当函数被调用时压入栈顶,执行完毕后弹出。如果栈溢出(如无限递归),会抛出RangeError: Maximum call stack size exceeded。在事件循环中,只有当调用栈完全为空时,才会从队列中取新任务执行。

输出顺序:1 → 4 → 3 → 2
解释:console.log(1)console.log(4)是同步代码,直接执行。setTimeout回调进入宏任务队列,Promise.then回调进入微任务队列。同步代码执行完后,先清空微任务队列(执行3),再处理宏任务队列(执行2)。
点击"经典面试题"预设,使用单步模式亲自观察每一步!

Web APIs是浏览器提供的异步能力(如定时器、AJAX、DOM事件、fetch等),它们独立于JS引擎运行。当调用setTimeout时,浏览器会在Web APIs中启动定时器,JS引擎继续执行后续代码——这就是非阻塞的关键。定时器到期后,回调被推入相应的任务队列,等待事件循环调度。