Suggest an editImprove this articleRefine the answer for “Event loop in Node.js”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)The **event loop** is an infinite loop that pulls ready callbacks from queues (timers, I/O, promises) and runs them phase by phase, as long as there is at least one task left. **Key point:** the event loop is exactly what lets a single V8 thread serve thousands of concurrent connections without blocking on I/O.Shown above the full answer for quick recall.Answer (EN)Image## 1. What the Event Loop is, in plain words The **Event Loop** is an infinite loop that: 1. pulls tasks from queues (for example, callbacks from `fs`, `setTimeout`, `http`, `Promise`, and so on), 2. runs them in a specific order (by phase), 3. keeps spinning as long as there is at least one task. The idea: instead of many threads, there is one thread (the V8 JS engine) that quickly switches between tasks without blocking on I/O. ## 2. Components involved in the Event Loop | Component | Role | |---|---| | **V8** | Runs the JavaScript code itself | | **libuv** | Implements the Event Loop, Thread Pool and async I/O | | **Queue** | Holds callbacks and tasks waiting to run | | **OS Kernel** | Performs I/O operations and notifies libuv when they're ready | ## 3. How the Event Loop works Simplified: 1. Node.js runs synchronous code (for example, the body of `app.js`); 2. When it hits an async operation (`fs.readFile`, `setTimeout`, `fetch`, `net`, and so on), it hands it to **libuv**; 3. libuv runs it in the background (or delegates it to the OS); 4. When the operation finishes, the result is placed in an **event queue**; 5. The **Event Loop** pulls ready callbacks from the queue and runs them in V8. ## 4. Phases of the Event Loop Each iteration of the Event Loop is called a **tick**. One iteration passes through **several phases** (simplified): | Phase | What it does | Examples | |---|---|---| | **1. timers** | Runs callbacks from `setTimeout()` and `setInterval()` | `setTimeout(cb, 0)` | | **2. pending callbacks** | Handles callbacks for some system operations | TCP errors, sockets | | **3. idle, prepare** | Internal libuv phases (rarely used directly) | - | | **4. poll** | Waits for new I/O events and runs their callbacks | `fs.readFile()`, network requests | | **5. check** | Runs callbacks from `setImmediate()` | `setImmediate(cb)` | | **6. close callbacks** | Closes resources | `socket.on('close')` | After that, the cycle repeats as long as there are tasks. ## 5. Separate queues: microtasks and macrotasks Node.js, like the browser, has **two task queues**: - **macrotasks**, ordinary tasks (`setTimeout`, `setImmediate`, I/O callbacks); - **microtasks**, small tasks (`Promise.then`, `process.nextTick`). ### The order: 1. The current macrotask runs (for example, from `timers`); 2. Then *all microtasks* run (`Promise.then`, `process.nextTick`); 3. Then the Event Loop moves to the next phase. `process.nextTick()` runs even **before** `Promise.then()`, in a special "internal" queue. ## 6. A step-by-step example ```javascript setTimeout(() => console.log('timeout'), 0); setImmediate(() => console.log('immediate')); Promise.resolve().then(() => console.log('promise')); process.nextTick(() => console.log('nextTick')); console.log('sync'); ``` **Result:** ```javascript sync nextTick promise timeout immediate ``` **Why:** 1. `sync` runs immediately; 2. `nextTick` runs before the next phase starts; 3. `promise` is a microtask, runs after `nextTick`; 4. `timeout` runs in the timers phase; 5. `immediate` runs in the check phase. ## 7. Why the Event Loop makes Node.js fast - Node.js does not block on I/O (reading files, network requests); - all asynchronous operations run in the background; - while they run, the Event Loop keeps handling other tasks. This lets Node.js serve **thousands of concurrent connections** on a single thread. ## 8. When the Event Loop "freezes" If you run a heavy synchronous operation (for example, `while(true)` or a `for` loop over millions of iterations), the Event Loop "blocks": neither timers nor callbacks can run. The fix: offload heavy work to **Worker Threads**, **child_process**, or **native addons**. ## 9. Visualization (text) ```javascript ┌──────────────────────────────┐ │ JS runs in V8 │ │ (synchronous code, promises)│ └──────────────┬───────────────┘ ▼ ┌──────────────────────────────┐ │ libuv │ │ - Event Loop │ │ - Thread Pool │ └──────────────┬───────────────┘ ▼ ┌──────────────────────────────┐ │ The operating system │ │ (I/O, files, network, timers)│ └──────────────────────────────┘ ``` ## 10. Summary | Component | What it does | |---|---| | **Event Loop** | Controls the order tasks run in | | **libuv** | Implements the event cycle and background operations | | **V8** | Runs the JS code and its callbacks | | **Thread Pool** | Runs heavy operations off the main thread | | **Queue** | Holds callbacks and microtasks/macrotasks |For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.