Skip to content
GeeksSmith
intermediate 6 min read

Event Loop & Asynchronous JavaScript

The Event Loop is the single-threaded coordinator that constantly monitors the Call Stack and transfers pending callbacks from the Microtask Queue and Task Queue once the stack is empty.

Why it matters in interviews

Understanding the exact microtask/macrotask priority order and task starvation is the #1 filter interviewers use to separate junior engineers from senior engineers who can debug race conditions, UI jank, and hydration issues.

Visual & Interactive Explanation

Interactive Event Loop Runtime Simulator

JavaScript SnippetStep 1 of 8
console.log("1: Start");

setTimeout(() => {
  console.log("2: Timeout (Macro)");
}, 0);

Promise.resolve().then(() => {
  console.log("3: Promise (Micro)");
});

console.log("4: End");
Runtime Event:Initial state: Script is loaded and ready to execute in the Global Execution Context.
Call Stack (LIFO)
global()
Web APIs (Async)
Idle
Microtasks (Promises)
Queue empty
Task Queue (Macrotasks)
Queue empty
Console Output Stream
[No output yet]

Code Examples & Implementation

Microtask vs Macrotask Execution Order
console.log("1");

setTimeout(() => console.log("2"), 0);

Promise.resolve().then(() => {
  console.log("3");
  queueMicrotask(() => console.log("4"));
});

console.log("5");

// Output Order:
// 1 -> 5 -> 3 -> 4 -> 2
// Explanation: 1 & 5 are sync. 3 is microtask. 4 is microtask spawned inside microtask (drained in same tick). 2 is macrotask.
Yielding to Main Thread to Prevent INP Jitter
async function processHugeList(items: string[]) {
  for (let i = 0; i < items.length; i++) {
    doCpuHeavyWork(items[i]);
    
    // Yield every 50 items to let browser paint and handle clicks
    if (i % 50 === 0) {
      if ('scheduler' in window && 'yield' in (window as any).scheduler) {
        await (window as any).scheduler.yield();
      } else {
        await new Promise((resolve) => setTimeout(resolve, 0));
      }
    }
  }
}

Interview-Ready Answers

JavaScript is single-threaded. Synchronous code runs on the Call Stack. Async tasks delegate to Web APIs. Microtasks (Promise.then) run immediately after synchronous code and before any Macrotask (setTimeout).

Official Documentation & Specifications

Follow-up Questions & Deep Dives

🎯 Code Output — What Does This Print?

Question 1medium
console.log("A");
setTimeout(() => console.log("B"), 0);
Promise.resolve().then(() => console.log("C"));
console.log("D");
Question 2hard
console.log("1");

setTimeout(() => {
  console.log("2");
  Promise.resolve().then(() => console.log("3"));
}, 0);

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

console.log("6");
Question 3tricky
setTimeout(() => console.log("timeout"), 0);

Promise.resolve()
  .then(() => console.log("promise1"))
  .then(() => console.log("promise2"))
  .then(() => console.log("promise3"));

console.log("sync");
Question 4hard
async function foo() {
  console.log("foo start");
  await Promise.resolve();
  console.log("foo end");
}

console.log("script start");
foo();
console.log("script end");
Question 5tricky
console.log("start");

setTimeout(() => console.log("timeout1"), 0);
setTimeout(() => console.log("timeout2"), 0);

Promise.resolve().then(() => {
  console.log("promise1");
  queueMicrotask(() => console.log("microtask1"));
});

queueMicrotask(() => console.log("microtask2"));

console.log("end");

Common Mistakes & Anti-Patterns

  • Assuming setTimeout(fn, 0) runs immediately after the current line (it must wait for microtasks and queue turn)
  • Creating microtask starvation loops that block browser painting and user input
  • Running long loops (>50ms) on the main thread without yielding or Web Worker delegation

Real-World Architectural Scenario

A user clicks 'Export 50,000 PDF records' and the entire browser tab freezes, causing high INP (>800ms) and dropped clicks. How do you re-architect it?

Rate Your Readiness

Rate how comfortably you can explain this in an interview to update your global readiness gauge:

Rate your confidence: