Web Fundamentals

Event Loop: Understanding JavaScript Execution Model

Web Fundamentals Map

Rendering & Browser Architecture

Critical Rendering PathScript Loading Patterns (async/defer)Event Loop Deep DiveJavaScript Module Systems (CJS, ESM, UMD)Dynamic Module Loading (import())Import on InteractionImport on VisibilityBrowser Rendering Pipeline & Layout ThrashingRendering Strategies (CSR, SSR, SSG, ISR)Streaming SSR & Progressive HTMLIslands ArchitectureReact Server ComponentsFramework Reactivity (React, Vue, Svelte, Solid)HTTP/1.1 vs HTTP/2 vs HTTP/3 (QUIC)DNS Resolution & TTL Caching

Performance

Core Web Vitals: LCP, INP, CLSPerformance Optimization Trade-offsCritical Resource PrioritizationCode Splitting & Dynamic ImportsTree Shaking & Dead Code EliminationLazy LoadingResource Hints: Preload, Prefetch & PreconnectText Compression: Gzip & BrotliImage & Video OptimizationAdaptive LoadingList VirtualizationWeb Workers vs Main ThreadMemory Leaks: Detection & PreventionManaging Third-Party ScriptsHow CDNs WorkHTTP Caching Deep DiveService Workers & Offline StrategyPWA Fundamentals

Security

Cross-Site Scripting (XSS)Cross-Site Request Forgery (CSRF)CORS ExplainedCORS Preflight, Credentials & MisconfigurationsContent Security Policy (CSP)Why is HTTPS Secure? (TLS/SSL)Authorization Best PracticesCookie Security & Session Hardening

State & Data Architecture

State Management Guide (Context vs Zustand vs Redux)React Query & Server State CachingData Fetching PatternsCaching StrategiesPagination: Offset vs Cursor-BasedReal-time Communication (WebSocket, SSE, Polling)
mediumWeb Fundamentals

Event Loop: Understanding JavaScript Execution Model

Learn the interview-ready mental model, practical trade-offs, and production patterns for this web fundamentals topic.

Topic content

TL;DRSynchronous → Drain all Microtasks → One Task → Drain Microtasks → Render → Repeat
Very High Signal
Google
Meta
Zeta
Rippling
30-Second Answerstart every interview with this

The JavaScript Event Loop manages execution order: current synchronous code runs to completion on the Call Stack, then all Microtasks (Promises, queueMicrotask) are drained, followed by one Task (macrotask like setTimeout), then microtasks again, before a rendering opportunity. This model explains why Promise callbacks run before setTimeout callbacks.

The Call Stack is the head chef cooking one dish at a time. Microtasks are urgent VIP orders that must be completed before any new regular orders (Tasks). The Event Loop is the manager who ensures the kitchen finishes all urgent work before starting the next regular order, and checks for rendering (UI updates) between cycles.

Call Stack (Sync Code)
Drain Microtask Queue (fully)
Run 1 Task (macrotask)
Drain Microtask Queue again
Render Opportunity (rAF + Paint)
Repeat

1Core Components

Call Stack: runs synchronous JS to completion. Microtask Queue: high priority (Promise.then, queueMicrotask). Task Queue (Macrotasks): lower priority (setTimeout, DOM events). Event Loop: coordinates the flow.

event-loop.jsjs
console.log('Sync');

Promise.resolve().then(() => console.log('Microtask'));

setTimeout(() => console.log('Task'), 0);

2Execution Order Rules

1. Run current script fully. 2. Drain ALL microtasks. 3. Take ONE task from task queue. 4. Drain microtasks again. 5. Render opportunity. Repeat. Microtasks queued during draining still run before the next task.

3Step-by-Step Example

For the classic example with logs 1,7 + Promise + queueMicrotask + multiple setTimeouts, the output is: 1 7 3 6 5 2 8 4. Microtasks run before any timers, and nested microtasks are processed in the same drain phase.

example.jsjs
console.log('1');
setTimeout(() => console.log('2'), 0);

Promise.resolve().then(() => {
  console.log('3');
  setTimeout(() => console.log('4'), 0);
  Promise.resolve().then(() => console.log('5'));
});

queueMicrotask(() => console.log('6'));
console.log('7');
setTimeout(() => console.log('8'), 0);

4Microtasks vs Tasks

Microtasks (Promise.then, queueMicrotask, MutationObserver) run immediately after sync code and between tasks. Tasks (setTimeout, events, network callbacks) run one at a time with rendering opportunities in between.

Key Takeaways
  • ✓Synchronous code always runs first on the Call Stack
  • ✓Microtasks are drained completely before any new task or rendering
  • ✓setTimeout(0) does NOT mean immediate — it waits for microtasks
  • ✓Nested microtasks still run in the same drain phase
  • ✓Keep tasks short to avoid blocking the main thread and rendering
PreviousNext

Topic Guide

On this page