Promise Hacks Out, queueMicrotask() In


Stop turning functions into promises just for async execution - Meet queueMicrotask()
If you’ve ever wrapped a function in Promise.resolve().then(...)
just to make it run asynchronously, you’re not alone.
It’s a common trick and it work, but it’s not the most intentional way to do it.
JavaScript actually gives us a dedicated API for this exact purpose: queueMicrotask()
.
The Backstory: Microtasks vs Macrotasks
To understand why queueMicrotask()
exists, we need to zoom in on the JavaScript event loop.
JavaScript execution is single-threaded, but it’s designed to handle asynchronous events. The event loop processes tasks in two main queues:
Macrotask queue → Timers (
setTimeout
,setInterval
), UI rendering, network callbacks, etc.
These are scheduled after the current stack finishes and after all microtasks are cleared.Microtask queue → Promise
.then()
callbacks,MutationObserver
callbacks, and…queueMicrotask()
.
These run immediately after the current stack finishes but before any macrotasks.That difference is huge:
Output :
A
D
B - microtask
C - macrotask
Microtasks always jump the line in front of macrotasks.
The Old Hack: Promises for Microtasks
Before queueMicrotask()
existed, the easiest way to get into the microtask queue was:
It works, but it comes with:
Unnecessary Promise creation overhead.
Slightly less clear intent, looks like you’re working with promises, but you’re not.
A bit of mental friction for newcomers who expect
.then()
to mean “waiting for some async operation”.
The Modern Way: queueMicrotask()
queueMicrotask()
was introduced to solve exactly this problem:
Schedule a function to run as a microtask, without pretending it’s about Promises.
Things to keep in mind regarding queueMicrotask()
Always runs in the microtask queue (just like
.then()
callbacks).No promise object is created - it’s lightweight.
Executes after the current synchronous code finishes, but before any macrotask.
When to Use queueMicrotask()
Deferring work until after the current synchronous operation finishes, without waiting for the next macrotask.
Avoiding promise creation overhead when all you want is microtask scheduling.
Library development where precise async ordering matters.
Preventing race conditions - for example, ensuring callbacks run after all sync setup is complete.
Pros
Lighter and more explicit than wrapping in
Promise.resolve().then(...)
.Clear signal to readers: "I want this to run in the microtask phase."
Slight performance edge in tight loops or high-frequency async scheduling.
Cons (Shared with Promises)
Can starve the event loop if abused (e.g., recursively queuing microtasks).
No way to cancel once scheduled.
Runs so soon that it can block rendering if the work is heavy.
TL;DR
queueMicrotask()
is like.then()
callbacks, but faster and more explicit.Use it when you want microtask timing without faking it with Promises.
Don’t abuse it in long-running loops, or you might block UI updates.
If you’ve been using Promises just to get microtask behavior - it’s time to stop.queueMicrotask()
was literally made for that.
If you enjoyed this article and want to discover more such lesser-known but powerful JavaScript, ReactJS, NextJS features, follow me for more insights.
LinkedIn
Twitter
Subscribe to my newsletter
Read articles from Jiya Agrawal directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
