setTimeout schedules a callback to run after a delay, but the delay is a minimum, not a promise of exact execution time. Once the timer expires, its task must wait for the event loop to process it. section 13.2.1
Why a 10 ms timer can run later
If mainline code runs for 18 ms while a click handler is waiting, a timer set for 10 ms may not run until the click handler finishes—at 28 ms in the example. section 13.2.1
Listing 13.3. Pseudocode for our time-out and interval demo
<button id="myButton"></button>
<script>
setTimeout(function timeoutHandler(){ #A
/*Some timeout handle code that runs for 6ms*/ #A
}, 10); #A
setInterval(function intervalHandler(){ #B
/*Some interval handle code that runs for 8ms*/ #B
}, 10); #B
const myButton = document.getElementById("myButton");
myButton.addEventListener("click", function clickHandler(){ #C
/*Some click handle code that runs for 10ms*/ #C
}); #C
/*Code that runs for 18ms*/
</script>
Trace a 10 ms timeout alongside interval and click handlers to see how queued work delays execution. section 13.2.1
