Suppose two clicks are waiting to be handled, and the first handler resolves a promise. The promise callback runs before the second click handler—even if that click was already queued. That is the practical importance of a microtask: it gets its turn after the current task finishes, before the event loop moves to another task. section 13.1.2
The event loop uses at least a macrotask queue and a microtask queue. Macrotasks include actions such as running mainline JavaScript, handling clicks, and handling timers. Microtasks are smaller pieces of deferred work, including promise callbacks and DOM mutation changes. Neither kind of task interrupts one that is already running. section 13.1 section 13.4
A resolved promise still waits
In a click handler, `Promise.resolve().then(() => { /* callback */ });` queues a microtask; it does not run the callback immediately. The rest of that handler finishes first. The event loop then processes the queued promise callback before taking the next waiting click task. section 13.1.2
Listing 13.2. Pseudocode for our event loop demo with two queues
<button id="firstButton"></button>
<button id="secondButton"></button>
<script>
const firstButton = document.getElementById("firstButton");
const secondButton = document.getElementById("secondButton");
firstButton.addEventListener("click", function firstHandler(){
Promise.resolve().then(() => { #A
/*Some promise handling code that runs for 4 ms*/ #A
}); #A
/*Some click handle code that runs for 8 ms*/
});
secondButton.addEventListener("click", function secondHandler(){
/*Click handle code that runs for 5ms*/
});
/*Code that runs for 15ms*/
</script>
Trace the two click handlers and the promise callback. Notice that registering the callback occurs inside the first handler, while executing it is a separate step. section 13.1.2
This priority matters to the page you see. The browser may re-render between macrotasks, but it processes queued microtasks before that opportunity. Updating application state in a microtask can therefore avoid an intermediate render that shows inconsistent state. “As soon as possible” does not mean “right now”: the current task must finish first. section 13.1 section 13.1.2
