Suggest an editImprove this articleRefine the answer for “What phases does the Event Loop consist of?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)One iteration (tick) of the Event Loop passes through six phases in order: **timers → pending callbacks → idle/prepare → poll → check → close callbacks**, with microtasks (`process.nextTick`, `Promise.then`) running between every phase. **Key point:** `setTimeout(cb, 0)` fires in the timers phase while `setImmediate(cb)` fires in the check phase, so their relative order outside an I/O callback isn't guaranteed.Shown above the full answer for quick recall.Answer (EN)Image## 1. What an Event Loop "phase" is Node.js's Event Loop is implemented via the **libuv** library. Each iteration (tick) of the Event Loop is split into **phases**, logical stages where different types of callbacks run. One **iteration** of the Event Loop is called a **tick**. Once all phases finish, the cycle starts over, as long as there are tasks. ## 2. The main phases of the Event Loop | # | Phase | What it does | Example callbacks | |---|---|---|---| | 1 | **timers** | Runs callbacks from `setTimeout()` and `setInterval()` | `setTimeout(cb, 0)` | | 2 | **pending callbacks** | Runs certain deferred system callbacks (I/O errors, TCP, etc.) | Socket errors, `TCP.onconnection` | | 3 | **idle, prepare** | Internal libuv phases (not used directly from JS) | - | | 4 | **poll** | The main I/O-waiting phase. Runs ready I/O callbacks or waits for new events | `fs.readFile()`, network events | | 5 | **check** | Runs callbacks from `setImmediate()` | `setImmediate(cb)` | | 6 | **close callbacks** | Runs resource-closing callbacks | `socket.on('close')`, `stream.destroy()` | ## 3. Schematically (in one Event Loop iteration): ```javascript ┌───────────────────────────────────────┐ │ 1. timers │ ← setTimeout(), setInterval() ├───────────────────────────────────────┤ │ 2. pending callbacks │ ← system callbacks (I/O) ├───────────────────────────────────────┤ │ 3. idle, prepare │ ← internal libuv phases ├───────────────────────────────────────┤ │ 4. poll │ ← waiting for and handling I/O events ├───────────────────────────────────────┤ │ 5. check │ ← setImmediate() ├───────────────────────────────────────┤ │ 6. close callbacks │ ← socket.on('close'), stream.on('close') └───────────────────────────────────────┘ ``` Then a new iteration (tick) begins. ## 4. How `setTimeout()` and `setImmediate()` relate A very common interview question. | Function | Where it runs | Roughly when | |---|---|---| | `setTimeout(cb, 0)` | **timers** | At the start of the next Event Loop cycle | | `setImmediate(cb)` | **check** | At the end of the current Event Loop cycle | **Example:** ```javascript setTimeout(() => console.log('timeout'), 0); setImmediate(() => console.log('immediate')); ``` The result can be: ```javascript timeout immediate ``` or: ```javascript immediate timeout ``` It all depends on where the code ran from: before or after an I/O callback. ## 5. The special microtask queue Besides the Event Loop's phases, there are **microtasks**, callbacks from: - `Promise.then()` / `catch()` / `finally()`; - `process.nextTick()`. They **don't belong to any phase**, but run **between phases**: after every executed callback, the Event Loop **runs all pending microtasks**. ### Priority order: 1. `process.nextTick()` runs **before** microtasks. 2. Microtasks (`Promise.then`, `queueMicrotask`). 3. Then it moves to the next Event Loop phase. ## 6. An example with promises and nextTick ```javascript setTimeout(() => console.log('timeout'), 0); Promise.resolve().then(() => console.log('promise')); process.nextTick(() => console.log('nextTick')); setImmediate(() => console.log('immediate')); ``` **Result:** ```javascript nextTick promise timeout immediate ``` Why: 1. `nextTick` and `promise` run through the microtask queue; 2. then the `timers` phase (timeout); 3. then the `check` phase (immediate). ## 7. What's special about the `poll` and `check` phases ### The **poll** phase: - The Event Loop's main phase. - This is where Node.js **waits for new I/O events**. - If the queue is empty: - and timers exist, the Event Loop moves to the `timers` phase; - if not, the Event Loop **sleeps**, waiting for I/O. ### The **check** phase: - Runs `setImmediate()` callbacks. - If `poll` finished early (with no events), control passes quickly to `check`. ## 8. The `close callbacks` phase Wraps up the cycle: - runs callbacks tied to closing resources (`close`, `destroy`, `disconnect`); - for example, after `socket.destroy()` or `process.exit()`. ## 9. A simplified view of the full cycle ```javascript ┌────────────────────────────────────┐ │ timers (setTimeout, setInterval) │ ├────────────────────────────────────┤ │ pending callbacks (I/O) │ ├────────────────────────────────────┤ │ idle, prepare │ ├────────────────────────────────────┤ │ poll (waiting for I/O events) │ ├────────────────────────────────────┤ │ check (setImmediate) │ ├────────────────────────────────────┤ │ close callbacks (closing) │ └────────────────────────────────────┘ ▲ │ │ ▼ microtasks (Promises, nextTick) ``` ## 10. Summary | Phase | What it does | Examples | |---|---|---| | **timers** | Runs callbacks from `setTimeout` / `setInterval` | `setTimeout(cb, 1000)` | | **pending callbacks** | System callbacks from I/O operations | TCP, DNS | | **idle, prepare** | Internal libuv housekeeping steps | - | | **poll** | Waits for I/O, handles its callbacks | `fs.readFile`, `net`, `http` | | **check** | Runs `setImmediate` | `setImmediate(cb)` | | **close callbacks** | Closing resources | `socket.on('close')` | | **microtasks** | Between-phase tasks | `Promise.then()`, `process.nextTick()` |For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.