Suggest an editImprove this articleRefine the answer for “Microtasks in JavaScript”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**Microtasks are small tasks that run right after the current code (the current macrotask) and before the next macrotask from the queue starts.** They live in a separate structure, the Microtask Queue, and have higher priority than macrotasks. Their sources are `Promise.then`, `Promise.catch`, `queueMicrotask` and `MutationObserver`. When the stack empties, the Event Loop runs **all** microtasks back to back until the queue is empty, and only then takes a single macrotask. ```javascript setTimeout(() => console.log('macro'), 0); Promise.resolve().then(() => console.log('micro')); // micro, then macro ``` **Key point:** the Event Loop order is the stack, then all microtasks, then the next macrotask.Shown above the full answer for quick recall.Answer (EN)Image**Microtasks are small tasks that run right after the current code (the current macrotask) and before the next macrotask from the queue begins.** They form a separate structure, the Microtask Queue. ## Theory ### TL;DR - A microtask is a callback the Event Loop runs after the current code but before any macrotask. - The main sources are `Promise.then`, `Promise.catch`, `queueMicrotask` and `MutationObserver`. - The microtask queue is drained completely, while only one task is taken from the macrotask queue per turn. - Microtasks have higher priority, so `Promise.then` always beats `setTimeout(..., 0)`. - Spawning microtasks endlessly "freezes" the Event Loop: macrotasks and rendering never get control. - The order is: the stack, all microtasks, the next macrotask. ### Quick example ```javascript console.log('1'); setTimeout(() => console.log('2'), 0); Promise.resolve().then(() => console.log('3')); console.log('4'); ``` The resulting output order: ```text 1 4 3 2 ``` ### The key idea JavaScript has two levels of tasks: | Type | Examples | When it runs | | --- | --- | --- | | **Macrotasks (Tasks)** | `setTimeout`, `setInterval`, DOM events, network callbacks | After the stack is cleared | | **Microtasks** | `Promise.then`, `Promise.catch`, `queueMicrotask`, `MutationObserver` | Right after the current task, **before** the next macrotask | In other words, after the current code (a function, for example) has finished, the **Event Loop** first checks the **microtask queue**. If there is anything in it, all of those tasks run **one after another** until the queue is empty. ### Walking through the example 1. `console.log('1')` runs immediately. **Output:** `1` 2. `setTimeout(..., 0)`: the callback lands in the **macrotask queue** (task queue). 3. `Promise.then(...)`: the callback lands in the **microtask queue**. 4. `console.log('4')` runs immediately. **Output:** `4` 5. The current stack is empty, so **all microtasks** run, that is `console.log('3')`. 6. Only after that do macrotasks run, that is `console.log('2')`. ### What creates microtasks | Source | Example | | --- | --- | | **Promise** | `Promise.resolve().then(...)` | | **queueMicrotask()** | `queueMicrotask(() => { ... })` | | **MutationObserver** | Watching DOM changes | `async`/`await` belongs here too: the continuation after an `await` is scheduled as a microtask. ### Microtasks vs macrotasks | Property | Microtasks | Macrotasks | | --- | --- | --- | | Queue | Microtask Queue | Task Queue | | Examples | `Promise.then`, `queueMicrotask` | `setTimeout`, `setInterval`, `click` | | Priority | **Higher**, they run earlier | Lower | | When they run | After the current code, but before the next event | After all microtasks | ### Be careful with microtasks If you keep adding new microtasks inside `then` forever, the engine **never reaches** the next macrotask and you end up with a "frozen" Event Loop: ```javascript function loop() { Promise.resolve().then(loop); } loop(); // the browser will hang ``` The stack does not overflow here, because every microtask completes properly. The microtask queue simply never becomes empty, so timers, event handlers and page repaints never get their turn. ### Terms at a glance | Term | Description | | --- | --- | | **Microtask** | A small task that runs after the current code and before the next macrotask | | **Microtask queue** | Holds `Promise.then`, `queueMicrotask` and similar callbacks | | **Priority** | Higher than that of macrotasks | | **Event Loop order** | The stack, then all microtasks, then the next macrotask | ### Common mistakes - **Treating `Promise.then` and `setTimeout(..., 0)` as equals.** A promise is a microtask and will always run first, no matter the order in the code. - **Thinking a microtask is just a "faster timer".** It is a different queue with a different priority, not a smaller delay. - **Scheduling microtasks recursively for background work.** That blocks rendering; use `setTimeout` or `requestIdleCallback` for chunked work. - **Forgetting that the continuation after `await` is a microtask too.** That is why code after `await` runs later than people expect, yet still before any timer. - **Confusing the microtask queue with the call stack.** Microtasks only run once the stack is already empty.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.