Shaibal S
Shaibal S

Reputation: 23

Sequence of execution for JavaScript setTimeout

I am trying to understand the way setTimeout gets executed.

In the sample below, I was expecting to see 'Inside setTimeout' as the second line in the console log.

But, I always see 'Inside setTimeout' as the third line in the console log.

This is what I see in the log consistently:

First
Last
Inside setTimeout

Any idea why is it behaving this way?

<script>
console.log('First');
// NOTE: 0 milliseconds.
setTimeout(function() {console.log('Inside setTimeout')}, 0);
console.log('Last');
</script>

Upvotes: 1

Views: 1307

Answers (2)

Abhijith S
Abhijith S

Reputation: 532

Working of the setTimeout(function, delayTime) with an example: More details can be found here.

function main(){
  console.log('A');
  setTimeout(
    function display(){ console.log('B'); }, 0);
    console.log('C');
}
main();

//  Output
//  A
//  C
//  B
  1. The call to the main function is first pushed into the stack (as a frame). Then the browser pushes the first statement in the main function into the stack which is console.log(‘A’). This statement is executed and upon completion that frame is popped out. Alphabet A is displayed in the console.
  2. The next statement (setTimeout() with callback exec() and 0ms wait time) is pushed into the call stack and execution starts. setTimeout function uses a Browser API to delay a callback to the provided function. The frame (with setTimeout) is then popped out once the handover to browser is complete (for the timer).
  3. console.log(‘C’) is pushed to the stack while the timer runs in the browser for the callback to the exec() function. In this particular case, as the delay provided was 0ms, the callback will be added to the message queue as soon as the browser receives it (ideally).
  4. After the execution of the last statement in the main function, the main() frame is popped out of the call stack, thereby making it empty. For the browser to push any message from the queue to the call stack, the call stack has to be empty first. That is why even though the delay provided in the setTimeout() was 0 seconds, the callback to exec() has to wait till the execution of all the frames in the call stack is complete.
  5. Now the callback exec() is pushed into the call stack and executed. The alphabet C is display on the console. This is the event loop of javascript.

so the delay parameter in setTimeout(function, delayTime) does not stand for the precise time delay after which the function is executed. It stands for the minimum wait time after which at some point in time the function will be executed.

--Copied from medium

PS: The best working video example by Philip Roberts.

Upvotes: 0

T.J. Crowder
T.J. Crowder

Reputation: 1074168

Even with a 0ms timeout, it still schedules the function to be called asynchronously. The way setTimeout works is:

  • Do some validations on the input
  • Add the function to a list to be called as of X time
  • Return

Later, when the specified amount of time has passed, the browser will queue a task to call the function, which will be processed by the event loop when the tasks in front of it have been processed.

It never calls the function immediately. That would chaotic; by always calling it asynchronously, it's consistent. (That's also why a promise's then and catch handlers are always called asynchronously, even if the promise is already settled.)

All of the gory details are in the specification.

Upvotes: 2

Related Questions