What Is Settimeout Doing When Set to 0 Milliseconds

What is setTimeout doing when set to 0 milliseconds?

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:

  • Concurrency model and event loop—MDN
  • The JavaScript event loop: explained—Carbon Five

Why is setTimeout(fn, 0) sometimes useful?

In the question, there existed a race condition between:

  1. The browser's attempt to initialize the drop-down list, ready to have its selected index updated, and
  2. Your code to set the selected index

Your code was consistently winning this race and attempting to set drop-down selection before the browser was ready, meaning that the bug would appear.

This race existed because JavaScript has a single thread of execution that is shared with page rendering. In effect, running JavaScript blocks the updating of the DOM.

Your workaround was:

setTimeout(callback, 0)

Invoking setTimeout with a callback, and zero as the second argument will schedule the callback to be run asynchronously, after the shortest possible delay - which will be around 10ms when the tab has focus and the JavaScript thread of execution is not busy.

The OP's solution, therefore was to delay by about 10ms, the setting of the selected index. This gave the browser an opportunity to initialize the DOM, fixing the bug.

Every version of Internet Explorer exhibited quirky behaviors and this kind of workaround was necessary at times. Alternatively it might have been a genuine bug in the OP's codebase.


See Philip Roberts talk "What the heck is the event loop?" for more thorough explanation.

Why is the `setTimeout` callback called after function execution, even if the delay is 0 ms?

When you create a promise, or call an async function, or set a timeout for 0 milliseconds, the function is immediately queued into the Javascript event loop. Essentially, the function is added to a queue of functions to call, and once the javascript interpreter has nothing to do it'll start calling those functions. So, when you set a timeout for 0 milliseconds, it queues the console.log("m"), then calls the console.log("s"), then it has nothing to do so it finishes the queued console.log("m"), which is why it's out of order.

Why does a setTimeout delay of 0 still run after all other synchronous code in a for loop?

JavaScript, both in the browser and on the server, runs as an event loop. The runtime is constantly polling for events. Events consist of user actions (e.g. DOM element x was clicked), I/O (data came back from I/O or ajax call), and timer events (in this case). setTimeout(fn, 0) simply adds an event to be processed by the event loop at minimum when 0 milliseconds have elapsed. It will always execute after the current event has been processed.

What is the difference between setTimeout(fn, 0) and setTimeout(fn, 1)?

I think the answer is "It depends" now.

We can run the code in different platform and browsers:

function setTimeouts() {
setTimeout(function() { console.log(2); }, 2);
setTimeout(function() { console.log(1); }, 1);
setTimeout(function() { console.log(0); }, 0);
}

for (var i = 0; i < 10; i++) {
setTimeouts();
}

Does the non-specified delay in setTimeout function means zero-delay?

As mentioned by the setTimeout documentation, the delay is an optional value that will be set to 0 if not specified.

delay Optional

The time, in milliseconds (thousandths of a second), the timer should wait before the specified function or code is executed. If this parameter is omitted, a value of 0 is used, meaning execute "immediately", or more accurately, as soon as possible. Note that in either case, the actual delay may be longer than intended; see Reasons for delays longer than specified below.



Related Topics



Leave a reply



Submit