Suggest an editImprove this articleRefine the answer for “What is the event loop”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**The event loop is the mechanism inside the JavaScript engine that drives code execution, handles asynchronous operations and coordinates the call stack with the task queues. It works like an organizer: when the stack is empty it takes the next job from the microtask queue first (`Promise.then`, `queueMicrotask`), and only when that is empty from the macrotask queue (`setTimeout`, events, I/O). The event loop is what makes single threaded JavaScript asynchronous and non blocking.** ```javascript console.log('1'); setTimeout(() => console.log('2'), 0); // macrotask Promise.resolve().then(() => console.log('3')); // microtask console.log('4'); // output: 1, 4, 3, 2 ``` **Key point:** asynchronous callbacks run only when the call stack is empty, and microtasks always go before the next macrotask.Shown above the full answer for quick recall.Answer (EN)Image**The event loop is the mechanism inside the JavaScript engine** that drives code execution, handles asynchronous operations and coordinates the call stack with the task queues. The event loop is exactly what makes JavaScript asynchronous and non blocking, even though the language itself is single threaded. ## Theory ### TL;DR - The event loop decides which task runs now and which one waits, so the main thread is never blocked. - An asynchronous callback enters the stack only when the stack is empty. - Microtasks (`Promise.then`, `queueMicrotask`) have higher priority than macrotasks (`setTimeout`, events, I/O). - After each macrotask the engine drains the entire microtask queue before taking the next macrotask. - If synchronous code never finishes, the event loop never reaches the queues at all. ### Quick example ```javascript console.log('1'); setTimeout(() => console.log('2'), 0); Promise.resolve().then(() => console.log('3')); console.log('4'); ``` Output: ```javascript 1 4 3 2 ``` Why: 1. The synchronous code runs first (`1`, `4`). 2. The promise callback (`.then`) goes into the **microtask** queue. 3. `setTimeout` goes into the **macrotask** queue. 4. The event loop first runs every microtask (`3`), then picks up the next macrotask (`2`). ### The main participants To understand the event loop you need four structures: 1. **Call Stack** - where the current code runs: functions and expressions. 2. **Task Queue / Callback Queue** - the **macrotask** queue: timers, events, `setTimeout`, `setInterval`, I/O. 3. **Microtask Queue** - the **microtask** queue: `Promise.then()`, `queueMicrotask()`, plus `process.nextTick()` in Node.js. 4. **Event Loop** - the loop that watches everything: if the stack is empty it takes a job from the microtask queue; if that is empty it takes a job from the macrotask queue. Schematically: ```javascript +--------------------+ | Call Stack | <- runs the current code +---------^----------+ | (empty?) v +--------------------+ | Microtask Queue | <- Promise, queueMicrotask +---------^----------+ | (empty?) v +--------------------+ | Task Queue | <- setTimeout, setInterval, I/O +--------------------+ Event loop checks the queues and moves jobs into the stack ``` ### How the event loop works, step by step 1. JavaScript runs the **synchronous code**, top to bottom. 2. When an **asynchronous operation** appears, it is handed to the external **Web APIs** (a timer or `fetch`, for example). 3. When the operation completes, its callback lands in the matching **task queue**. 4. When the **call stack is empty**, the event loop takes a job from a queue and pushes it onto the stack. 5. After all **microtasks** have run, the event loop moves on to the next **macrotask**. This repeats continuously, in an endless loop. If the stack is never freed, the queues are never processed at all: ```javascript setTimeout(() => console.log('2'), 0); while (true) {} // infinite loop ``` The event loop will never reach the `setTimeout`, because the stack never empties. Asynchronous jobs run **only when the stack is empty**. ### Microtasks vs macrotasks | Task type | Examples | When it runs | | --- | --- | --- | | **Microtasks** | `Promise.then`, `queueMicrotask` | right after the current code and before the next macrotask | | **Macrotasks** | `setTimeout`, `setInterval`, `fetch`, I/O, DOM events | after all microtasks | In other words, microtasks have the higher priority. ### In the browser vs in Node.js | Environment | Event loop specifics | | --- | --- | | **Browser** | Web APIs provide timers, `fetch`, DOM events | | **Node.js** | has its own phases: timers, I/O, check, close, `nextTick` and so on | But the idea is the same in both: one thread, asynchrony through the event loop. ### Summary | Component | Purpose | | --- | --- | | **Call Stack** | runs the current code | | **Web APIs** | carry out asynchronous operations | | **Task Queue** | holds macrotask callbacks | | **Microtask Queue** | holds promises and the microtask jobs | | **Event Loop** | moves ready jobs from the queues into the stack | ### Common mistakes - Expecting `setTimeout(fn, 0)` to run `fn` immediately. A delay of 0 only means "as soon as possible once the stack and all microtasks are done". - Thinking the event loop is part of the language. It belongs to the runtime, the browser or Node.js, not to the ECMAScript specification. - Getting the priorities wrong: a promise created after a timer still runs first, because microtasks come first. - Scheduling microtasks from inside microtasks forever: the microtask queue is drained completely, so such a loop freezes the page just like `while (true)`. - Expecting `setTimeout(fn, 100)` to fire exactly after 100 ms. That is a minimum delay; the real time depends on how busy the stack is.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.