Why Does Settimeout() "Break" for Large Millisecond Delay Values

Why does setTimeout() break for large millisecond delay values?

This is due to setTimeout using a 32 bit int to store the delay so the max value allowed would be

2147483647

if you try

2147483648

you get your problem occurring.

I can only presume this is causing some form of internal exception in the JS Engine and causing the function to fire immediately rather than not at all.

setTimeout fires immediately if the delay more than 2147483648 milliseconds

The upper limit of setTimeout is 0x7FFFFFFF (or 2147483647 in decimal)

This is because setTimeout uses a 32bit integer to store its delay value, so anything above that will cause the problem

If you want a timeout which fires after an X ammount of days, you could try to use setInterval instead with a lower delay value like this

function setDaysTimeout(callback,days) {
// 86400 seconds in a day
var msInDay = 86400*1000;

var dayCount = 0;
var timer = setInterval(function() {
dayCount++; // a day has passed

if(dayCount == days) {
clearInterval(timer);
callback.apply(this,[]);
}
},msInDay);
}

You would then use it like this

setDaysTimeout(function() {
console.log('Four days gone');
},4); // fire after 4 days

Can setTimeout's delay argument be effected at all by sub-millisecond inputs?

Modern browsers throttle setTimeout/setInterval calls to a minimum of once every 4 ms.

Also, MDN says that:

The delay argument is converted to a signed 32-bit integer. This
effectively limits delay to 2147483647 ms, since it's specified as a
signed integer in the IDL.

So, any fractions of milliseconds are not going to be effective.

The times are not JS specifications - they are specified in the DOM standards.

4 ms is specified by the HTML5 spec and is consistent across browsers
released in 2010 and onward. Prior to (Firefox 5.0 / Thunderbird 5.0 /
SeaMonkey 2.2), the minimum timeout value for nested timeouts was 10
ms.

However in Node JS, the timers used are the system-specific high precision timers. They (the system timers) can go in resolutions up to nanoseconds. It should be experimented in Node JS if the timer delays are saved as integers.

JavaScript setTimeout doesn't work properly

As per the Documentation, the setTimeOut Function supports a maximum of 24.8 days [MDN Ref] that is equal to 2147483647

Thus when you do 2147483648 you essentially get is (2147483648 - 2147483647 = 1)

However, when you use 52147483648 as per the epoch time converter this is only 17 days ahead in the future which is less than 24.8 days thus it does not convert it

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 timeout 599147937792 faster than 0?

There is a comment about this, you should read the article closely.

Info

The smallest setTimeout timeout value allowed by the HTML5 specification is 4 ms. Smaller
values should clamp to 4 ms.

Therefore, the first two tests below should have about the same result.

P.S. Some browsers freak out when you use a value greater than 599147937791 for the
timeout (i.e. they use 0 or 4 ms instead), hence the last test.

Essentially, Javascript has internal handling for 0 and 599147937792 as they qualify for over/underflow values for setTimeout and they are rounded to a default minimum accepted value 4 ms. This is probably because it is unreasonable to ask for a 0 ms delay as it would probably take longer than this to even process the function and determine this is what the user wants. The error on the larger value is probably due to the fact that computers have limits how big/small of a number that you can represent.

To understand why the large and small values return after 4 for example is that the internal handling takes time as well, a very small amount, but time. Consider these two timelines:

Timeline 1

  1. setTimeout(...,0) is called
  2. The function checks boundary conditions (something like if (time < 4) {// use 4})
  3. The function needs an extra step here to change the value from 0 -> 4.
  4. Now it sets the timeout for 4 ms

Timeline 2

  1. setTimeout(...,4) is called
  2. The function checks boundary conditions (something like if (time < 4) {// use 4})
  3. Everything is ok, moves along.
  4. Now it sets the timeout for 4 ms

Step 3 in the two timelines takes longer in the first case as there is the extra step of changing the value. Both will wait for the same amount of time, but the second one will start its timing ever so slightly sooner. This is much the same with 599147937792, except the check will be for the upper bound.

The phrasing "freaks out" makes me think it might look more like

try { 
// try with the given input
} catch (Exception) {
// Ahh I freaked out, just use 4 instead!!!!111!!!
}

Why are some JavaScript developers using setTimeout for one millisecond?

It's an old hack. If an event needs to be triggered after another event you can use setTimeout with 1ms to make sure the event is triggered after the other event.

Why does setTimeout() break for large millisecond delay values?

This is due to setTimeout using a 32 bit int to store the delay so the max value allowed would be

2147483647

if you try

2147483648

you get your problem occurring.

I can only presume this is causing some form of internal exception in the JS Engine and causing the function to fire immediately rather than not at all.

setTimeout runs function immediately

SetTimeout has Maximum Delay Value

Browsers including Internet Explorer, Chrome, Safari, and Firefox store the delay as a 32-bit signed integer internally.

This causes an integer overflow when using delays larger than 2,147,483,647 ms (about 24.8 days), resulting in the timeout being executed immediately.

Please check more details here:

https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout#:~:text=Maximum%20delay%20value&text=This%20causes%20an%20integer%20overflow,the%20timeout%20being%20executed%20immediately.



Related Topics



Leave a reply



Submit