Work scheduled for the main JavaScript thread is processed FIFO. This includes callbacks from various async tasks, such as setTimeout
and ajax completions, and event handlers. The only exception is that in the main popular environments (browsers and Node), the resolution callback of a native Promise
jumps the queue (more accurately, goes in a different higher-priority queue), see my answer here for details on that.
But leaving aside native promise resolution callbacks:
but all the three functions will be blocked until the for loop finish. At 18ms, the for
loop finished, so what order does these functions will be invoked. (fn1,fn2,fn3) or (fn2,fn3,fn1)
The time you give setTimeout
is approximate, because when that time comes due the JavaScript UI thread may be busy doing something else (as you know); there's also a minimum time required by the (newish) spec, but the degree to which it's enforced varies by implementation. Similarly, you can't guarantee that the click event will be queued at 6ms, or that the ajax completion will occur at exactly 7ms.
If that code started, and the browser did the 10ms precisely, and the click
event was queued exactly 6ms in, and the ajax request completed at exactly 7ms, then the order would be: fn2
(the click
handler), fn3
(the ajax completion), fn1
(the setTimeout
), because that's the order in which they'd be queued.
But note that these are extremely tight timings. In practice, I expect the order the callbacks were queued would be effectively random, because the timing of the click
would vary, the timing of the ajax
would vary, etc.
I think this is a better example:
var start = +new Date();
// Queue a timed callback after 20ms
setTimeout(function() {
display("20ms callback");
}, 20);
// Queue a timed callback after 30ms
setTimeout(function() {
display("30ms callback");
}, 30);
// Queue a timed callback after 10ms
setTimeout(function() {
display("10ms callback");
}, 10);
// Busy-wait 40ms
display("Start of busy-wait");
var stop = +new Date() + 40;
while (+new Date() < stop) {
// Busy-wait
}
display("End of busy-wait");
function display(msg) {
var p = document.createElement('p');
var elapsed = String(+new Date() - start);
p.innerHTML = "+" + "00000".substr(elapsed.length - 5) + elapsed + ": " + msg;
document.body.appendChild(p);
}
The order of output will be the two loop messages followed by the 10ms callback, 20ms callback, and 30ms callback, because that's the order in which the callbacks are queued for servicing by the main JavaScript thread. For instance:
+00001: Start of busy-wait
+00041: End of busy-wait
+00043: 10ms callback
+00044: 20ms callback
+00044: 30ms callback
...where the +
numbers indicate milliseconds since the script started.