DEV Community

Cover image for JavaScript's queueMicrotask(): Running Code ASAP (But Not Right Now)
Gajanan Patil
Gajanan Patil

Posted on

JavaScript's queueMicrotask(): Running Code ASAP (But Not Right Now)

Ever needed to run a piece of JavaScript code right after the current script finishes, but before the browser does anything else like rendering or handling timer callbacks? Meet queueMicrotask()!

It's a fundamental part of understanding JavaScript's concurrency model and the Event Loop.

What Does It Do?

In simple terms, queueMicrotask(callback) schedules a function (callback) to be executed in the microtask queue. Think of it as saying: "Run this function as soon as the current synchronous block of code is done executing, no matter what, and before handling less urgent things."

The Crucial Timing: Microtasks vs. Macrotasks

This is where queueMicrotask() shines and differs from something like setTimeout(callback, 0). Here's the general flow of the event loop:

  1. Execute the current synchronous script/task until the call stack is empty.
  2. Process the Microtask Queue: Execute all functions currently in the microtask queue, one by one, until the queue is empty. New microtasks added during this process are also executed before moving on.
  3. (Optional: Perform UI rendering updates, if needed and conditions allow).
  4. Process the Macrotask Queue: Take one task from the macrotask queue (like a setTimeout callback, setInterval, I/O operation, user interaction handler) and execute it. This execution might queue more microtasks.
  5. Repeat from step 2.

Key takeaway: Microtasks (queueMicrotask, Promise .then/.catch/.finally) have higher priority and run before the next macrotask (setTimeout, setInterval, rendering).

Why Use It?

  • Fine-grained Control: Perform cleanup or follow-up actions immediately after a block of code finishes, without yielding to the browser's rendering or other macrotasks.
  • Consistency with Promises: Promise callbacks are handled as microtasks. Using queueMicrotask allows you to schedule work with the same timing semantics.
  • Frameworks/Libraries: Useful internally in frameworks or libraries to schedule updates or reactions after state changes but before the browser might repaint.

Quick Example

console.log('Start');

// Macrotask - will run much later
setTimeout(() => {
  console.log('setTimeout (Macrotask)');
}, 0);

// Microtask - runs after 'End', before setTimeout
queueMicrotask(() => {
  console.log('queueMicrotask (Microtask)');
});

// Promise.then also queues a Microtask
Promise.resolve().then(() => {
  console.log('Promise.then (Microtask)');
});

console.log('End');

/*
Expected Output:
---------------
Start
End
queueMicrotask (Microtask)
Promise.then (Microtask)
setTimeout (Macrotask)
*/

Enter fullscreen mode Exit fullscreen mode

Conclusion

queueMicrotask() gives you precise control to schedule code execution immediately after the current task, bypassing the queue for larger tasks like timers or rendering. It's a powerful tool when you need that "as soon as possible, but still async" behavior, especially when working alongside Promises.

It's been 3 (tough) years since I last wrote a post on dev.to and it felt nice writing post again. Will try to maintain streak going ahead.

Top comments (0)