Suggest an editImprove this articleRefine the answer for “The queueMicrotask() function”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**`queueMicrotask(callback)` adds a function to the microtask queue: it runs after all of the current synchronous code has finished, but before any macrotask, that is, before `setTimeout`, `setInterval`, event handlers and I/O.** In behaviour it is a full equivalent of `Promise.resolve().then(callback)`, only without creating a Promise object, which makes the call slightly cheaper and simpler. The Event Loop drains the microtask queue completely, including microtasks that were added while it was being drained, and only then picks up the next macrotask. The function returns `undefined`, was standardised in ECMAScript 2019 and is available in every modern browser and in Node.js. ```javascript console.log('A'); queueMicrotask(() => console.log('B')); console.log('C'); // A, C, B ``` **Key point:** `queueMicrotask()` puts a function into the microtask queue, which is always drained after the current code and before the first timer.Shown above the full answer for quick recall.Answer (EN)Image**`queueMicrotask(callback)` puts the given function into the microtask queue, and it runs right after the current synchronous code finishes, but before any macrotask.** It is the simplest way to defer an action to "the next moment the stack is empty" without creating a promise for it. ## Theory ### TL;DR - `queueMicrotask(fn)` adds `fn` to the Microtask Queue and returns `undefined`. - The microtask runs once the Call Stack is empty, but before the first macrotask (`setTimeout`, `setInterval`, events, I/O). - The behaviour is identical to `Promise.resolve().then(fn)`, only without the cost of creating a Promise object. - The Event Loop drains the microtask queue completely, including microtasks added while it is being drained. - Adding microtasks endlessly blocks the Event Loop: no macrotask will ever get its turn. - Standardised in ECMAScript 2019, supported by all modern browsers and Node.js. ### Quick example ```javascript console.log('A'); queueMicrotask(() => console.log('B')); console.log('C'); // Output: // A // C // B ``` First all of the synchronous code runs (`A`, then `C`). Then the Event Loop sees that the stack is empty and runs the microtask (`B`) before moving on to macrotasks. ### What `queueMicrotask()` actually does The signature is as simple as it gets: ```javascript queueMicrotask(callback); ``` The function does two things: - it adds `callback` to the **microtask queue**; - it guarantees that the callback runs **after the current function finishes**, but **before** any `setTimeout`, `setInterval`, event or other macrotask. Under the hood the order is: 1. The current code in the Call Stack runs to completion. 2. Once it finishes, the Event Loop checks the **microtask queue**. 3. All microtasks in the queue run **in order**, one after another. 4. Only then does it take the next **macrotask** (a `setTimeout` callback, for example). ### Ordering next to a timer ```javascript setTimeout(() => console.log('timeout'), 0); queueMicrotask(() => console.log('microtask')); console.log('sync'); // Output: // sync // microtask // timeout ``` The order comes from three levels: 1. `sync` is synchronous code, so it runs first; 2. `microtask` is the microtask queue, which is drained immediately after the synchronous code; 3. `timeout` is the macrotask queue, which the Event Loop reaches last. Even `setTimeout(fn, 0)` will never beat a microtask: a zero delay only means "queue this macrotask as soon as possible", not "run it immediately". ### Comparison with `Promise.then` `queueMicrotask()` works **exactly like** `Promise.resolve().then(callback)`, but **without creating a Promise object**, which makes it slightly faster and simpler. ```javascript Promise.resolve().then(() => console.log('microtask via Promise')); queueMicrotask(() => console.log('microtask via queueMicrotask')); ``` Both callbacks land in the **microtask queue** and run **before any timers**. The only difference is the cost: the promise version additionally allocates a Promise object and a `then` chain, while `queueMicrotask()` simply puts the function into the queue. If you do not need a result and are not building a chain, `queueMicrotask()` states the intent more precisely. ### Nested microtasks and the risk of blocking the Event Loop All microtasks run back to back. If you create a new microtask from inside a microtask, it joins the same queue and runs **before control moves to a macrotask**: ```javascript queueMicrotask(() => { console.log('A'); queueMicrotask(() => console.log('B')); }); // Output: // A // B ``` That leads straight to the danger: the microtask queue can be made endless. ```javascript function loop() { queueMicrotask(loop); } loop(); ``` This code will hang the Event Loop: microtasks keep running forever, and no macrotask (`setTimeout`, clicks, rendering, network callbacks) ever gets executed. In a browser it effectively freezes the tab. ### Summary | Property | Value | | --- | --- | | What it does | Adds a function to the microtask queue | | When it runs | After the current code, but before any macrotask | | Equivalent | `Promise.resolve().then(fn)` | | Queue | Microtask Queue | | Returns | `undefined` | | Use case | A light, fast alternative to promises for microtasks | | Standard | ECMAScript 2019, all modern browsers and Node.js | ### Common mistakes - **Confusing it with `setTimeout(fn, 0)`.** A timer is a macrotask, so it runs after every microtask, even with a zero delay. - **Assuming the microtask runs "immediately".** It still waits for the current function to finish completely and for the stack to empty. - **Queueing microtasks recursively.** That is not "splitting work into chunks", it is a guaranteed Event Loop block, because the microtask queue never yields to macrotasks. - **Using it for heavy computation.** A microtask blocks rendering exactly like synchronous code. To split heavy work you need macrotasks (`setTimeout`) or a separate Worker. - **Expecting a return value.** `queueMicrotask()` always returns `undefined`, there is no chain like in a promise and no way to read the callback's result. - **Relying on it for error handling.** An exception inside the callback does not reach any `catch`, it surfaces as an unhandled error, so it has to be handled inside the function itself.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.