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:
- The browser's attempt to initialize the drop-down list, ready to have its selected index updated, and
- 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
setTimeout(...,0)
is called- The function checks boundary conditions (something like
if (time < 4) {// use 4}
) - The function needs an extra step here to change the value from
0 -> 4
. - Now it sets the timeout for
4
ms
Timeline 2
setTimeout(...,4)
is called- The function checks boundary conditions (something like
if (time < 4) {// use 4}
) - Everything is ok, moves along.
- 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
JavaScript Extract Certain Properties from All Objects in Array
Load JSON from Local File with Http.Get() in Angular 2
Force Page Zoom at 100% with Js
Store Jquery Selector in Variable
Html5 <Audio> Playback with Fade in and Fade Out
Make Checkbox Behave Like Radio Buttons with JavaScript
Class Methods as Event Handlers in JavaScript
Change How Fast "Title" Attribute's Tooltip Appears
How to Implement a Stack and a Queue in JavaScript
Convert Character to Ascii Code in JavaScript
Typeof !== "Undefined" VS. != Null
Syntax for an Async Arrow Function
Difference Between "Module.Exports" and "Exports" in the Commonjs Module System