Back
Web Fundamentals

Event Loop: Understanding JavaScript Execution Model

Web Fundamentals
Build & Deployment: Monorepo, CI/CD, Strategies & Release SafetyState Management: Choosing the Right SolutionRedux: Predictable State Container (RTK + RTK Query)React Query (TanStack Query): Server State CachingData Fetching Patterns: REST, GraphQL, tRPC & Real-timeGraphQL Fundamentals for Frontend: Shape, Caching, and TradeoffsgRPC-Web Fundamentals: Browser Constraints and Proxy ModelCaching Strategies: Client, Server & EdgeData Normalization: Organizing State for PerformanceAPI Design Best Practices: Pagination, Errors, Versioning & Type SafetyAPI Versioning Strategies for Frontend CompatibilityPagination: Offset vs Cursor-BasedRate Limiting & API Resilience: Retries, Backoff, Jitter, IdempotencyHow Frontend Developers Can Handle Millions of API Requests Without Crashing EverythingBrowser Storage: Cookies, SessionStorage, LocalStorage, IndexedDBReal-time Communication: WebSockets, SSE & PollingWebRTC: Real-Time Communication in the BrowserCore Web Vitals: LCP, INP & CLSPerformance Optimization Trade-offsCritical Resource Prioritization: Optimize Loading OrderCode Splitting: Optimize Bundle Size with Dynamic ImportsTree Shaking: Eliminate Dead Code from Your BundleLazy Loading: Load Resources On-DemandResource Hints: Preload, Prefetch & PreconnectText Compression: Gzip and BrotliImage & Video Optimization: Modern Formats & TechniquesAdaptive Loading: Optimize for Device & NetworkList Virtualization: Render Large Lists EfficientlyWeb Workers vs Main Thread: Offloading Heavy WorkMemory Leaks in Frontend Apps: Detection & PreventionManaging Third-Party Scripts: Optimization StrategiesHow CDNs Work: Edge Delivery, Caching & PerformanceHTTP Caching Deep Dive: Cache-Control, ETag & RevalidationService Workers & Offline Strategy: Cache First, Network First & Update LifecyclePWA Fundamentals: Manifest, Installability & Offline UXCritical Rendering PathScript Loading: async vs deferEvent Loop: Understanding JavaScript Execution ModelJavaScript Module Systems: CJS vs ESM vs UMDDynamic Module Loading: import() FunctionImport on Interaction: Load When User InteractsImport on Visibility: Lazy Loading with IntersectionObserverBrowser Rendering Pipeline & Layout ThrashingRendering Strategies: CSR vs SSR vs SSG vs ISRStreaming SSR: Progressive HTML StreamingIslands Architecture: Independent Component HydrationReact Server Components: Zero-JS Server RenderingFramework Reactivity: React, Vue, Svelte & SolidHTTP/1.1 vs HTTP/2 vs HTTP/3 (QUIC) for Frontend PerformanceDNS Resolution: Path, TTL, Caching & Frontend ImpactCross-Site Scripting (XSS) AttacksCross-Site Request Forgery (CSRF) AttacksCORS Explained: Cross-Origin Resource SharingCORS Preflight in Practice: Credentials, Simple Requests & MisconfigurationsContent Security Policy (CSP)Why is HTTPS Secure? Understanding TLS/SSLAuthorization Best PracticesCookie Security & Session Hardening: SameSite, HttpOnly, Secure
mediumRendering & Browser Architecture

Event Loop: Understanding JavaScript Execution Model

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.

PropertyMicrotaskTask (Macrotask)
TimingAfter current script / after each taskAfter all microtasks
BehaviorHigh priority, drained fully before next taskLower priority, only one per loop cycle
ExamplesPromise.then, queueMicrotask, MutationObserversetTimeout, setInterval, DOM events
Use CaseDOM updates, state cleanup that must happen before renderScheduled work, I/O callbacks, timers

Microtask

Timing

After current script / after each task

Behavior

High priority, drained fully before next task

Examples

Promise.then, queueMicrotask, MutationObserver

Use Case

DOM updates, state cleanup that must happen before render

Task (Macrotask)

Timing

After all microtasks

Behavior

Lower priority, only one per loop cycle

Examples

setTimeout, setInterval, DOM events

Use Case

Scheduled work, I/O callbacks, timers

Common questions

  • ›“Explain the JavaScript Event Loop.”
  • ›“Why does Promise.then run before setTimeout(..., 0)?”
  • ›“Walk through this code and predict the output order.”
  • ›“What is the difference between microtasks and macrotasks?”

What interviewers look for

  • Clear mental model: sync → microtasks → task → microtasks
  • Understanding of nested microtask draining
  • Knowledge of rendering impact and main-thread blocking
  • Distinction between browser and Node.js behavior

Short answer (60 sec)

JavaScript runs synchronous code first, then drains the entire microtask queue (Promises, queueMicrotask), then processes one task (setTimeout etc.), drains microtasks again, and allows rendering. This repeats.

Detailed answer (senior level)

The full browser event loop is: current script → drain microtasks → one macrotask → drain microtasks → requestAnimationFrame callbacks → style/layout/paint/composite. Microtasks have higher priority and are fully exhausted before moving to the next task or render. This is why Promise callbacks always run before timers and why long tasks block the UI.

  • Thinking setTimeout(fn, 0) runs immediately
  • Forgetting that microtasks queued during draining still run before the next task
  • Confusing microtasks with tasks (macrotasks)
  • Assuming the same behavior in Node.js (process.nextTick is different)
  • Not realizing long-running tasks block rendering
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
Previous TopicScript Loading: async vs deferNext Topic JavaScript Module Systems: CJS vs ESM vs UMD

On this page