Event Loop

The **Event Loop** is the **heart of JavaScript’s concurrency model**. It’s a mechanism that **coordinates the execution of synchronous and asynchronous code** — making sure your app stays responsive, even while doing many things at once (like waiting for network requests, user input, or timers).

# Why It Exists JavaScript is **single-threaded**, meaning it can only do **one thing at a time**. So how can it handle multiple events like: * `setTimeout` * `fetch()` * user clicks * Promise resolutions …without blocking everything else? 👉 Enter the **Event Loop**.

# What Is It? The **Event Loop** is a continuously running **loop** that: 1. **Executes code on the call stack** 2. When the stack is empty, it: * **Checks the Microtask Queue** (e.g. resolved Promises) * Then **checks the Macrotask Queue** (e.g. timeouts, events) 3. Moves tasks from the queues to the stack to be executed > 🌀 It loops forever, processing one task at a time.

# Diagram Overview

digraph EventLoop { rankdir=TB; node [shape=box, style=filled, fontname=Helvetica]; // Core components CallStack [label="Call Stack\n(executing JS code)", fillcolor=lightblue]; MicrotaskQueue [label="Microtask Queue\n(Promise.then, queueMicrotask)", fillcolor=khaki]; MacrotaskQueue [label="Macrotask Queue\n(setTimeout, setInterval, DOM events)", fillcolor=lightcoral]; EventLoop [label="Event Loop\n(coordinates execution)", shape=ellipse, style=filled, fillcolor=white]; // Flow arrows EventLoop -> MicrotaskQueue [label="Check after stack clears", fontsize=10]; EventLoop -> MacrotaskQueue [label="Then check macrotasks", fontsize=10]; MicrotaskQueue -> CallStack [label="Drain microtasks", fontsize=10]; MacrotaskQueue -> CallStack [label="Run one macrotask", fontsize=10]; // Stack execution loop CallStack -> EventLoop [label="When empty", fontsize=10]; // Layout control { rank = same; MicrotaskQueue; MacrotaskQueue; } }

# Example: Order of Execution

console.log('A'); setTimeout(() => { console.log('B'); }, 0); Promise.resolve().then(() => { console.log('C'); }); console.log('D');

**Output:**

A D C B

# Why? 1. `A` and `D` run immediately (call stack) 2. `Promise.then(...)` goes into **microtask queue** 3. `setTimeout(..., 0)` goes into **macrotask queue** 4. After `D`, the **event loop** runs: * First: all microtasks → logs `C` * Then: macrotasks → logs `B`

# Key Components | Component | Description | | --------------- | --------------------------------------------- | | Call Stack | Executes synchronous code (functions, blocks) | | Microtask Queue | High-priority async tasks (e.g., Promises) | | Macrotask Queue | Regular async tasks (e.g., timers, events) | | Event Loop | Dispatcher that decides **what runs next** |

# Real-world Analogy Imagine a **chef in a kitchen**: * The chef (call stack) prepares one dish at a time. * The **waiter** (event loop) brings in orders. * Urgent tasks (microtasks) like "turn off the oven" go first. * Regular tasks (macrotasks) like "serve next table" come next.

# Summary * The **Event Loop** makes JavaScript **non-blocking**, even though it's single-threaded. * It coordinates between: * Call stack (what’s running now) * Microtask queue (high-priority async tasks) * Macrotask queue (timers, user events) * It ensures **everything runs in the correct order** and keeps your app responsive.