The event loop — the architecture behind every async concept
flowchart TD
Code["<b>i · Your code</b><br/>sync statements"]
--> Stack["<b>ii · Call Stack</b><br/>executes frame by frame (LIFO)"]
Stack --> Web["<b>iii · Web APIs</b><br/>setTimeout, fetch, DOM, I/O"]
Web --> MQ["<b>v · Microtask Queue</b><br/>promise .then, queueMicrotask"]
Web --> CQ["<b>iv · Callback Queue</b><br/>setTimeout, setInterval, events"]
MQ --> Loop
CQ --> Loop
Loop{"<b>vi · Event Loop</b><br/>stack empty?"} -- drain microtasks first --> Stack
Loop -- then one macrotask --> Stack
classDef head fill:#f5efe1,stroke:#6a8a4f,stroke-width:2px,color:#1a1915;
classDef sync fill:#fdecd3,stroke:#c2410c,stroke-width:2px,color:#1a1915;
classDef micro fill:#e7efd9,stroke:#587640,stroke-width:2px,color:#1a1915;
classDef macro fill:#e3e8f5,stroke:#4a5a8a,stroke-width:2px,color:#1a1915;
classDef hub fill:#f5e1e1,stroke:#8a4f4f,stroke-width:2px,color:#1a1915;
class Code head
class Stack sync
class Web,CQ macro
class MQ micro
class Loop hub-
Your code
The source you wrote — synchronous statements, function declarations, and calls that kick off async work.
-
Call Stack
LIFO frame stack. Pushes on call, pops on return. Never blocked by async — await suspends and pops the frame.
-
Web APIs
Browser/Node APIs that run outside the stack — timers, fetch, DOM listeners, I/O. When they complete, they queue a callback.
-
Callback Queue
Macrotask queue — setTimeout, setInterval, events, I/O. One macrotask per event-loop tick.
-
Microtask Queue
Promise .then/.catch/.finally, queueMicrotask, MutationObserver. ALL drained before the next macrotask.
-
Event Loop
The referee. When the stack is empty: drain every microtask, then take one macrotask. Repeat forever.
Comments
Comments are disabled in this environment. Set
PUBLIC_GISCUS_REPO,PUBLIC_GISCUS_REPO_ID, andPUBLIC_GISCUS_CATEGORY_IDto enable.