queueMicrotask() in the JavaScript Event Loop

`queueMicrotask()` explicitly schedules a callback to run as a microtask, which is processed at a microtask checkpoint before the event loop proceeds to a later task. It is useful when code needs to defer work without creating a timer or other task.

`queueMicrotask(callback)` adds `callback` to the environment's microtask queue. The callback does not execute immediately; it runs after the current synchronous JavaScript execution completes and when the runtime reaches a microtask checkpoint.

Microtasks are processed before the event loop takes the next task, such as a timer callback or many user-interface events. The queue is drained until no microtasks remain, so a microtask can enqueue another microtask that runs in the same checkpoint.

For frontend code, this makes `queueMicrotask()` useful for small deferred operations such as completing state-related bookkeeping after the current synchronous operation. Unlike `setTimeout(callback, 0)`, it does not schedule a separate timer task.

Microtasks should remain short. A callback that repeatedly queues more microtasks can delay rendering and other tasks because the runtime must continue processing the microtask queue before moving on.

Key points

Interview questions

What does `queueMicrotask()` do?

It schedules a callback to run as a microtask instead of executing it immediately. The callback waits until the current synchronous JavaScript execution finishes. It is then processed during a microtask checkpoint before later tasks are handled.

What is the output of code that logs before and after a `queueMicrotask()` call?

The synchronous logs appear first because the microtask is not executed during the current statement sequence. Once the current synchronous execution completes, the queued callback runs. Therefore, a log before the call and a log after the call both appear before the microtask's log.

How does `queueMicrotask()` compare with `setTimeout(fn, 0)`?

`queueMicrotask()` places the callback in the microtask queue, whereas `setTimeout` schedules a timer task. Microtasks are processed at the microtask checkpoint before the event loop proceeds to a later task. Consequently, replacing a zero-delay timer with `queueMicrotask()` can change observable ordering.

Why can excessive use of microtasks hurt frontend responsiveness?

The runtime processes queued microtasks before proceeding to later event-loop work. If microtasks continuously add more microtasks, the checkpoint can take a long time to finish. That can postpone tasks and, depending on the environment and workload, delay opportunities for rendering and user interaction. Microtasks are therefore best suited to short deferred operations.

What happens if a microtask queues another microtask?

The newly queued microtask is added to the microtask queue and is processed before the runtime proceeds to the next task. Microtask processing therefore continues until the queue is empty at that checkpoint. This behavior enables chained deferred operations but also means an unbounded chain can prevent progress to later event-loop work.