setTimeout and the Web Api

Kevin McCarthy
3 min readMar 2, 2018

--

Recently I was having a tough time testing some asynchronous behaviour and used setTimeout to try to understand some of the behaviour. Things did not go as I expected and I discovered I really didn’t understand setTimeout at all.

Below is a run through of what I learned about setTimeout and the Web Api.

setTimeout

My initial understanding of setTimeout was that it delayed taking the action by however many milliseconds you put at the end. Its syntax is like this.

setTimeout(() => { console.log("I'll appear after 3 seconds")}, 3000)

so setTimeout is a function which you pass two arguments to. The first argument is a function to be invoked and the second argument is the number of milliseconds you want it to wait to invoke said function.

setTimeout(functionToExecute, millisecondsToWaitBeforeExecuting)

lets test it out

Some examples

function consoleLogTwo() {
console.log(2)
}
console.log(1)
setTimeout(consoleLogTwo, 1000)
console.log(3)

So in this instance I’d expect to get back

1 
3
2

as its hanging around for 1 second before executing consoleLogTwo and as such has time to go ahead and console log 3.

What if we changed the setTimeout wait period to 0.

My gross misunderstanding of how setTimeout works

Based on my previous understanding of setTimeout this line

setTimeout(consoleLogTwo, 0)

meant execute consoleLogTwo immediately and was equivalent to

consoleLogTwo()

so with the following code

function consoleLogTwo() {
console.log(2)
}
console.log(1)
setTimeout(consoleLogTwo, 0)
console.log(3)

I’d expect to get back

1
2
3

HOWEVER!!!

I was very very wrong

I did not. I get back

1
3
2

again!

What is going on?

Even when I make the last step be a much longer step (printing out almost 5000 numbers)

function consoleLogTwo() {
console.log(2)
}
console.log(1)
setTimeout(consoleLogTwo, 0)
for(i = 3; i < 5000; i++){ console.log(i) }

it still returns two last

1
3
4
....
4998
4999
2

I thought I’d discovered something very interesting but when I showed the rest of the developers at my work they were all terribly unimpressed and said “Well yeah, cos it has to go off to the webApi so its at the back of the queue”

Helpful resources

So I was recommended this great video

which led me to this amazing tool loupe

This visualises what is happening when your javascript code is run.

The below examples I’ve slowed down to quarter speed so its easier to see what is happening.

Here is our example with the 1 second delay

gif showing runtime events of example with setTimeout at 1000 milliseconds

And here is our example with the 0 second delay

gif showing runtime events of example with setTimeout at 0 secs

In both examples it adds the executable line to the calls stack. If its part of the Javascript processor it executes immediately and moves onto the next line. However if its part of the WebApi like (setTimeout) it gets sent out to the Web Api. Once its completed it then moves to the callback queue. Once the call stack is empty it pulls in from the callback queue and gets executed. The only difference between the

 setTimeout(consoleLogTwo, 1000),

and

setTimeout(consoleLogTwo, 0) 

is the slight delay (you see the spinner spinning) between being added from Web Api to the Callback Queue.

It doesn’t matter if there is a 0 second delay, 1 second delay or even longer, once the time elapses it still gets sent to the callback queue and can’t execute until the call stack is empty.

I’d heartily encourage you to go watch the video and have a play around with loupe. I found it super helpful in my investigation.

--

--

No responses yet