Suggest an editImprove this articleRefine the answer for “Macrotask queue”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**A macrotask queue is the queue of large asynchronous tasks from which the event loop takes exactly one task per iteration.** It holds `setTimeout`, `setInterval`, `setImmediate` in Node.js, DOM event handlers, network callbacks and `MessageChannel`. After every macrotask the engine drains all microtasks first and only then picks the next macrotask, which is why `Promise.then` always fires before `setTimeout(..., 0)`. ```javascript setTimeout(() => console.log('macrotask'), 0); Promise.resolve().then(() => console.log('microtask')); // microtask // macrotask ``` **Key point:** one macrotask per event loop iteration, with the whole microtask queue drained in between.Shown above the full answer for quick recall.Answer (EN)Image**A macrotask queue is the queue of large asynchronous tasks that are executed one per Event Loop iteration.** Each macrotask is a "big" event: a timer fired, the user clicked, a network response arrived. The microtask queue has higher priority, so macrotasks always wait their turn. ## Theory ### TL;DR - A macrotask is a "big" asynchronous unit of work: `setTimeout`, `setInterval`, `setImmediate` (Node.js), DOM event handlers, network callbacks, `MessageChannel`. - Exactly **one** macrotask runs per Event Loop iteration. - After each macrotask the engine runs **all** microtasks that have piled up. - The order never changes: macrotask, all microtasks, next macrotask, all microtasks. - The macrotask queue is FIFO: tasks run in the order they were added. - Macrotasks have lower priority than microtasks, so `Promise.then()` fires before `setTimeout(..., 0)`. ### Quick example ```javascript console.log('1'); setTimeout(() => console.log('2 (macrotask)'), 0); Promise.resolve().then(() => console.log('3 (microtask)')); console.log('4'); ``` Result: ```javascript 1 4 3 (microtask) 2 (macrotask) ``` Why exactly this order: 1. `1` and `4` are printed synchronously, while the main script runs. 2. `.then()` schedules a **microtask**, which runs as soon as the stack is empty. 3. `setTimeout` schedules a **macrotask**, which runs only on the next Event Loop iteration. ### What lands in the macrotask queue Sources of macrotasks in the browser and in Node.js: - `setTimeout` - `setInterval` - `setImmediate` (Node.js only) - DOM event handlers: `click`, `load`, `input` and friends - network callbacks: `XMLHttpRequest`, a completed `fetch` - `MessageChannel` What they all share: the task arrives from "outside" the JavaScript engine, from a timer, from I/O or from the user. ### How the Event Loop works step by step A simplified but workable model of the loop: 1. **All synchronous code** runs (Call Stack). 2. Once the stack is empty, microtasks run. 3. Then the engine takes **one macrotask** from the queue and executes it. 4. When that macrotask finishes, **all** microtasks run: promise callbacks, `queueMicrotask`, `process.nextTick` and so on. 5. Then the **next macrotask** is taken, and again all microtasks after it. | Stage | What the engine does | | --- | --- | | 1 | Runs the synchronous call stack | | 2 | Runs all microtasks | | 3 | Takes one macrotask from the queue | | 4 | Runs all microtasks again | | 5 | Repeats the cycle | Schematically one tick looks like this: ```javascript // [ Tick 1 ] // Call Stack: synchronous code // v // Microtask Queue: promise callbacks // v // Macrotask Queue: setTimeout, events // v // Event Loop alternates between them ``` > A simple analogy: the Event Loop is a restaurant. > Macrotasks are the main courses, served one at a time. > Microtasks are the seasonings and side dishes added **between** courses. > After every main course the cook hands out all the seasonings first and only then starts the next order. ### Several macrotasks in a row ```javascript setTimeout(() => console.log('A'), 0); setTimeout(() => console.log('B'), 0); setTimeout(() => console.log('C'), 0); console.log('D'); ``` Result: ```javascript D A B C ``` All three `setTimeout()` calls land in the macrotask queue and run one at a time, in the order they were added (FIFO). The synchronous `console.log('D')` is always first because it never goes through a queue at all. ### Microtasks inside a macrotask ```javascript setTimeout(() => { console.log('1 (timeout)'); }, 0); setTimeout(() => { console.log('2 (timeout)'); Promise.resolve().then(() => console.log('3 (microtask)')); }, 0); ``` Result: ```javascript 1 (timeout) 2 (timeout) 3 (microtask) ``` Explanation: after every macrotask the engine runs all microtasks created during that macrotask. Line `3` is a microtask spawned by the second macrotask, so it runs **before** the engine picks the next macrotask. ### Macrotasks versus microtasks | Property | Macrotask | Microtask | | --- | --- | --- | | Examples | `setTimeout`, `setInterval`, DOM events, `fetch` | `Promise.then`, `queueMicrotask`, `process.nextTick` | | When they run | After the microtask queue is empty | After every macrotask, or after synchronous code | | How many per cycle | One per Event Loop iteration | All of them, until the queue is empty | | Priority | Low | High | | Kind of work | "External": timers, I/O, events | "Internal": JavaScript logic itself | The summary, one line per point: | Term | Description | | --- | --- | | **Macrotask queue** | The queue of large events executed by the browser or Node.js | | **What it stores** | Timers, I/O, event handlers, network callbacks | | **How it is drained** | One task per Event Loop iteration | | **After each one** | All microtasks are executed | | **Priority** | Lower than microtasks: `Promise` fires sooner than `setTimeout` | ### Common mistakes - **Assuming `setTimeout(fn, 0)` runs `fn` immediately.** Zero is a minimum delay, not a promise. The callback joins the macrotask queue and waits until the synchronous code is done and the microtask queue is empty. - **Mixing up the priorities.** `Promise.resolve().then(...)` always beats `setTimeout(..., 0)`, even when the promise is created later in the source. - **Thinking all macrotasks run in one iteration.** Only one does. The rest wait for later iterations, which is how the browser finds time to repaint between them. - **Creating an endless microtask chain.** If a microtask schedules another microtask, the queue never empties and no macrotask ever gets a turn: the page freezes. - **Relying on timer accuracy.** A long macrotask blocks the loop, so `setTimeout(fn, 100)` may fire much later than 100 ms. - **Confusing `setImmediate` with `setTimeout` in Node.js.** They belong to different phases of the loop, and their relative order at the top level of a module is not guaranteed.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.