Interactive Learning

JavaScript Event Loop

Understand how JavaScript stays responsive while handling timers, API requests, promises, and user interactions.

The Event Loop continuously checks whether the Call Stack is empty. When it is free, JavaScript runs pending Microtasks first, then Macrotasks, so slow work does not freeze the page.

Beginner Mental Model

What is the Event Loop?

JavaScript is single-threaded, which means it executes one piece of code at a time. The Event Loop is the mechanism that lets JavaScript continue working while slow operations happen in the background. When those operations are ready, the Event Loop brings their callbacks back only when the Call Stack is empty.

Call Stack

Where JavaScript runs the current line or function.

Browser APIs

Background helpers for timers, network requests, DOM events, and more.

Microtask Queue

High-priority queue for Promise callbacks and await continuations.

Macrotask Queue

Queue for timers, user events, and other callbacks.

Event Loop

The checker that moves queued work to the stack when the stack is empty.

Visual Diagram

Event Loop Flow

Use this diagram as the simple mental picture: the Event Loop waits for the Call Stack to become empty, runs Microtasks first, then handles Macrotasks.

Event Loop Flow Diagram
                 JavaScript Runtime

        +----------------------+
        |      Call Stack      |
        +----------+-----------+
                   |
          Is Stack Empty?
                   |
                  Yes
                   |
             Event Loop
                   |
        +----------+-----------+
        |                      |
        v                      v
 Microtask Queue        Macrotask Queue
(Promise, await)   (setTimeout, Events)
        |                      |
        +----------+-----------+
                   |
                   v
             Execute Callback
Step-by-Step Flow

How JavaScript Decides What Runs Next

Keep this order in your head. First synchronous code runs. Then, when the stack is empty, Microtasks run before Macrotasks.

1

Run synchronous code on the Call Stack.

2

Send slow work like fetch, timers, and events to Browser APIs.

3

When async work is ready, place its callback in the right queue.

4

Wait until the Call Stack becomes empty.

5

Run all Microtasks first, such as Promise callbacks.

6

Run one Macrotask next, such as setTimeout or a click handler.

7

Repeat the cycle so the UI stays responsive.

Real-World Analogies

Think of It Like a Restaurant

The chef does not pause the entire restaurant for one slow order. JavaScript works the same way: slow work is handled outside the Call Stack, then returned through queues.

Restaurant

The chef does not wait 20 minutes for pizza. Staff handles slow work in the background, and the manager brings it back when the counter is free.

Chef = JavaScript Engine
Kitchen Counter = Call Stack
Kitchen Staff = Browser APIs
Waiting Area = Queues
Manager = Event Loop

Coffee Shop

Fast work finishes first. Slow work waits outside the main counter, then returns when JavaScript is free.

Espresso runs now
Croissant waits briefly
Pizza waits longer
Easy Examples

Event Loop in Real Apps

These are the scenarios you see in product work: loading products, button clicks, timers, checkout APIs, and UI loading states.

E-commerce Product Load

console.log("Load Header");

fetch("/api/products").then(() => {
  console.log("Products Loaded");
});

console.log("Load Footer");

Output

Load Header
Load Footer
Products Loaded

The API request runs in the background. JavaScript continues rendering the page, then handles the products when the response is ready.

React Button Click

button.onclick = () => {
  console.log("Button Clicked");
};

console.log("App Ready");

Output

App Ready
Button Clicked after user clicks

The click callback waits until the user clicks. The browser queues it, and the Event Loop runs it when the stack is empty.

setTimeout Reminder

console.log("Start");

setTimeout(() => {
  console.log("Reminder");
}, 5000);

console.log("Continue Working");

Output

Start
Continue Working
Reminder

setTimeout is like setting a reminder. JavaScript does not stop working while the timer waits.

Checkout Page

console.log("Validate Payment");

fetch("/create-order").then(() => {
  console.log("Order Created");
  console.log("Redirect to Thank You Page");
});

console.log("Show Loading Spinner");

Output

Validate Payment
Show Loading Spinner
Order Created
Redirect to Thank You Page

The spinner appears immediately while the order API runs in the background. The UI does not freeze.

Interview Answer

30-Second Interview Answer

JavaScript is single-threaded and executes synchronous code using the Call Stack. When it sees asynchronous operations like fetch, setTimeout, or user events, the browser handles those operations in the background. Once the Call Stack becomes empty, the Event Loop first processes all pending Microtasks, such as Promise callbacks, and then processes Macrotasks, such as setTimeout callbacks. This keeps applications responsive without blocking the main thread.

Runtime Architecture

Visual representation of how the Event Loop orchestrates asynchronous code execution.

Call Stack
main()
Web APIs

Idle

Event Loop

Checks Call Stack → Microtasks → Rendering → Macrotasks

Microtask Queue

Empty

Callback Queue

Empty

How It Works

Call Stack: Executes synchronous code. Only one function at a time.

Web APIs: Handles asynchronous operations like setTimeout, fetch, and events.

Microtask Queue: Higher priority. Contains Promise callbacks and queueMicrotask.

Callback Queue: Lower priority. Contains setTimeout, setInterval callbacks.

Event Loop: Continuously checks if Call Stack is empty, then processes queues in order.

Interview Questions

Master these fundamental questions about the Event Loop that appear in technical interviews.

What is the Event Loop?
What is the Call Stack?
What is the difference between Microtask Queue and Callback Queue?
Why does Promise execute before setTimeout?
How does Async/Await work internally?
What happens when the Call Stack is not empty?

Key Takeaways

Single-threaded

One call stack at a time

Non-blocking

Async operations via APIs

Queue priority

Microtasks before Macrotasks

Collaborative

Browser controls rendering