Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When does setTimeout start counting down?

Here's the code I'm working with right now:

setTimeout(() => console.log('first'), 2000);
for (let i  = 0; i < 5000; i++) {
   console.log("printing...")
}
setTimeout(() => console.log('second'), 1000);

Expectation (setTimeout starts counting down right away)

  1. The first setTimeout will execute and start the timer for 2000 ms. However, since setTimeout callbacks are ran asynchronously, we'll have to skip over it and wait for the full call stack to finish before going through the callback queue.
  2. Go through the for loop. From my computer, it took around ~20 seconds for the whole for loop to finish running. Around a few seconds into the for loop, the first setTimeout should be done with it's timer now.
  3. The second setTimeout will then execute and start the timer. Similar to the first step
  4. Now that the call stack is done running, we go through the callback queue. Since the first setTimeout should've finished the delay first despite the higher delay, it should print "first" then "second"

Actual

printing...
/* Lots of "printing..." strings */
printing...
second
first

Seems to be the case that the second setTimeout still runs first. In this case, does this mean that the setTimeout countdowns only begin after the initial few lines of code are ran? I've tested this code on both Firefox and Chrome, and they seem to have the same behavior.

like image 996
seeingstars Avatar asked Oct 20 '25 13:10

seeingstars


1 Answers

Your expectation is correct, but the provided sample is deceptive. The for-loop does not take ~20 seconds. JavaScript finishes way sooner. It might take the JavaScript container (like your Browser) around 20 seconds to print everything, but the script just continues on.

//    [------ unit definition ------]  [--------- alias --------]
const MILLISECOND =    1             , MILLISECONDS = MILLISECOND;
const SECOND      = 1000*MILLISECONDS, SECONDS      = SECOND     ;

setTimeout(() => console.log('first'), 2*SECONDS);

console.log("starting heavy work");
const start = Date.now();
for (let i  = 0; i < 5000; i++) {
   console.log("printing...");
}
console.log(`finished work in ${(Date.now() - start)/SECONDS}s`);

setTimeout(() => console.log('second'), 1*SECOND);

setTimeout(() => console.log('second'), 1*SECOND) is executed less than a second after setTimeout(() => console.log('first'), 2*SECONDS). You can see how long the loop actually takes by comparing the start and end time of the loop.

Here is an example of some code that is actually busy for about 5 seconds.

//    [------ unit definition ------]  [--------- alias --------]
const MILLISECOND =    1             , MILLISECONDS = MILLISECOND;
const SECOND      = 1000*MILLISECONDS, SECONDS      = SECOND     ;


setTimeout(() => console.log("first"), 2*SECONDS);

console.log("starting heavy work");
const start = Date.now();
while (Date.now() - start < 5*SECONDS); // block the script for 5 seconds
console.log(`finished work in ${(Date.now() - start)/SECONDS}s`);

setTimeout(() => console.log("second"), 1*SECOND);
like image 68
3limin4t0r Avatar answered Oct 22 '25 01:10

3limin4t0r



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!