Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is setTimeout(fn, 0) sometimes useful?

I've recently run into a rather nasty bug, wherein the code was loading a <select> dynamically via JavaScript. This dynamically loaded <select> had a pre-selected value. In IE6, we already had code to fix the selected <option>, because sometimes the <select>'s selectedIndex value would be out of sync with the selected <option>'s index attribute, as below:

field.selectedIndex = element.index; 

However, this code wasn't working. Even though the field's selectedIndex was being set correctly, the wrong index would end up being selected. However, if I stuck an alert() statement in at the right time, the correct option would be selected. Thinking this might be some sort of timing issue, I tried something random that I'd seen in code before:

var wrapFn = (function() {     var myField = field;     var myElement = element;      return function() {         myField.selectedIndex = myElement.index;     } })(); setTimeout(wrapFn, 0); 

And this worked!

I've got a solution for my problem, but I'm uneasy that I don't know exactly why this fixes my problem. Does anyone have an official explanation? What browser issue am I avoiding by calling my function "later" using setTimeout()?

like image 612
Dan Lew Avatar asked Apr 22 '09 21:04

Dan Lew


People also ask

Why do we want sometimes to use setImmediate instead of using setTimeout?

The main advantage to using setImmediate() over setTimeout() is setImmediate() will always be executed before any timers if scheduled within an I/O cycle, independently of how many timers are present.

Why do we need clearTimeout?

clearTimeout() is a function which helps in clearing out the previously set time out time which was set by making use of the setTimeout() function which creates an ID value and this value, in turn, helps in clearing the time out which is sent as a parameter to JavaScript clearTimeout().

Is it good practice to use setTimeout?

Most of the time, we use “setTimeout()” to let some code run a certain period of time. However, it can cause problems when it is not used not carefully.

What is the purpose of setTimeout function in node JS?

What is setTimeout() in Node. js? The setTimeout function is used to call a function after the specified number of milliseconds. The delay of the called function begins after the remaining statements in the script have finished executing.


1 Answers

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.

like image 131
staticsan Avatar answered Oct 22 '22 01:10

staticsan