68

In JavaScript, setTimeout(callback, delay) means "call callback after delay milliseconds". But what if delay is 0? Should it call callback right away?

I am confused because of what I see when I run the following code:

setTimeout(function() { 
    console.log('AAA');
}, 0); // Call this in 0 milliseconds 

for (i = 0; i < 1000; i++) {
    console.log('BBB'); 
}
for (i = 0; i < 1000; i++) {
    console.log('CCC'); 
}
for (i = 0; i < 1000; i++) {
    console.log('DDD'); 
}
for (i = 0; i < 1000; i++) {
    console.log('EEE'); 
}

This logs the following to the console:

console_log

I expected to see AAA logged much sooner than that. There was time to execute 4000 other calls to console.log before a function which should have been called immediately.

Can someone explain what setTimeout is doing when the delay is set to 0 milliseconds?

Jordan Gray
  • 16,306
  • 3
  • 53
  • 69
DDan
  • 8,068
  • 5
  • 33
  • 52
  • 11
    Check [This](http://stackoverflow.com/questions/779379/why-is-settimeoutfn-0-sometimes-useful) – Trung Nov 27 '15 at 10:46
  • https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout – Nipuna Nov 27 '15 at 10:47
  • 1
    A great explanation on your question! Check [this](http://geekabyte.blogspot.in/2014/01/javascript-effect-of-setting-settimeout.html). – Deepak Biswal Nov 27 '15 at 10:49
  • Thanks for the links, great explanations. I would still keep my question open (as not duplicate) as it is showing the direct effect in a very simple way. – DDan Nov 27 '15 at 11:08
  • Looks like you dont know what is the `callbacks` –  Nov 27 '15 at 13:10

1 Answers1

118

A few useful facts might help clarify what's happening:

  1. JavaScript is single-threaded. Asynchronous callbacks are assigned to a message placed in a message queue.
  2. When no code is currently executing, the event loop polls the message queue, requesting the next message in line to be processed (executed).
  3. setTimeout adds a message (with the callback provided) to the end of this queue after the specified delay has elapsed.

(Note: this means the delay in a setTimeout call is not a sure thing; it is the minimum delay before the callback is executed. The actual time taken depends on how long it takes to process any messages ahead of it in the queue.)

So what happens if the delay is set to 0? A new message is added to the queue immediately, and will be processed when the currently executing code is finished and any previously-added messages have been processed.

What's happening in your code

When you invoke setTimeout

setTimeout(function() { 
    console.log('AAA');
}, 0);

…a message gets added to the queue with the specified callback. The rest of your code…

for (i = 0; i < 1000; i++) {
    console.log('BBB'); 
}
// etc.

…continues executing synchronously. Once it has completely finished, the event loop polls the message queue for the next message and finds the one with your setTimeout callback, which is then processed (the callback is run).

The callback only ever gets executed after the currently executing code has finished, no matter how long that takes.

Further reading

For more details on the event loop, see:

Jordan Gray
  • 16,306
  • 3
  • 53
  • 69
  • 7
    *"(Note: this means the delay in a setTimeout call is not a sure thing…)"* I never considered this. Thanks for pointing it out! – Jacob Apr 21 '16 at 20:50
  • 4
    Nice and concise answer that gives a good initial idea. Until now the best I found to this subject in terms of information/brevity quota. Thanks! – Wolfone Mar 25 '18 at 21:45