The only ways event bubbling can arise in a micro-queued task would be you dispatched a custom event on an element from within code being run from the microtask task queue, or if mutation observers are being internally signaled that the DOM has been modified (using "slotchange" events) from within a microtask. In both cases events are fired from within a microtask being executed, and event bubbling occurs synchronously in the JavaScript execution thread. In contrast, "native" events are fired by the browser and invoke event handlers asynchronously via the event loop.
Missing from the event scenario posted is that if multiple event handlers have been added for the same type of native event, the handlers are called from the event loop. Hence any microtasks enqueued by a handler will be executed before the control from the handler call returns to the event queue.
By way of demonstration of event flow for two "click" handlers:
"use strict";
document.querySelector("div").addEventListener("click", click1);
window.addEventListener("click", click2 /*, {capture:true}*/ );
function click1(event) {
console.log("click1 called for div")
queueMicrotask( ()=> console.log("microtask1 executes"));
console.log("click1 exits");
}
function click2(event) {
console.log("click2 called for window")
queueMicrotask( ()=> console.log("microtask2 executes"));
console.log("click2 exits");
}
div {background-color: yellow}
<div>Click this div</div>
or click the window,
Run the snippet and click the div to confirm that the div handler gets called, exits, and the microtask it spawned runs, before the window handler gets called after bubbling occurs. Note that although called from the event loop, the order they are called in will depend on whether event capture is used (commented out in the snippet).
If you replace queueMicrotask
with setTimeout
in the first click handler of the post, the call back function is no longer executed in the microtask queue before returning to the event loop, allowing the event loop to call the second click handler (for an event generated before timer expiry) before the timer callback.