Shekhar Joshi
Shekhar Joshi

Reputation: 1008

Call Stack while using setTimeout()

I am a bit confused about setTimeout.I want to confirm whether the output for the following code will always be:

inside abc
inside sample

The code:

function abc() {
    xyz();

    // interactions and modifications in DOM 
    $("#id1").append("something");
    $("#id2").val("set something");
    $("#id3").after("create some dynamic element");
    // 10 to 20 interaction more...

    console.log('inside abc');
}

function xyz() {
    setTimeout(function() {
        sample();
    },0);  
}

function sample() {
    console.log('inside sample')
}

It would be great,if somebody could explain the whole flow with the call stack.

Upvotes: 2

Views: 8925

Answers (3)

Sidd
Sidd

Reputation: 1397

Yes, the console output will always be the same. setTimeout's callback function is executed asynchronously after the context that called it is cleared. When setTimeout is called, it places its callback function on the stack and returns to the current execution context. When that is done (in your example, when abc is fully executed), the callback function is executed, which in your example basically calls sample immediately. So your code output will never be different.

The fact that setTimeout's callbacks are themselves executed asynchronously can be seen if you placed a longer setTimeout function somewhere inside abc before calling xyz:

function abc() {
    setTimeout(function(){
        console.log('wait')
    },1000);
    xyz();
    console.log('inside abc');
}
function xyz() {
    setTimeout(function(){
        sample();
    } ,0);  
}
function sample() {
    console.log('inside sample');
}
abc();    

...your console will log:

inside abc
inside sample
wait

To hold sample's execution until the longer timeout is complete you would need to place the setTimeout calling sample inside the longer setTimeout.

If setTimeout's callback is ever behaving differently, it's most likely due to being accidentally passed a function call instead of a function pointer, like this:

setTimeout(sample(),0);

instead of

setTimeout(sample,0)

Also, just in case you didn't know (or for others), you can add

debugger;

at any point(s) in your Javascript code and then run the code to view the callstack at that point using dev tools (in Chrome it is in the right panel under 'Sources').

Upvotes: 3

Samir Das
Samir Das

Reputation: 1908

setTimeout() will run asynchronously after finishing current execution block. So output should be same always:

inside abc
inside sample

Javascript internally manage an event queues internally for all async tasks. Every time it checks its async queue after finishing current execution block.

Upvotes: 3

JLRishe
JLRishe

Reputation: 101730

Yes, it will always have that output.

The callback inside a setTimeout will not be called until the execution context is clear - i.e. the currently executing sequence of code has finished.

This means that even if you do

setTimeout(function () { console.log("1 second!"); }, 1000);

var start = +new Date();
while ((+new Date()) - start < 5000) {}

1 second! will not be logged any sooner than 5 seconds have passed.

Upvotes: 7

Related Questions