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

I came across some unexpected behavior when passing a large millisecond value to setTimeout(). For instance,

setTimeout(some_callback, Number.MAX_VALUE);

and

setTimeout(some_callback, Infinity);

both cause some_callback to be run almost immediately, as if I'd passed 0 instead of a large number as the delay.

Why does this happen?


Solution 1:

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.

Solution 2:

You can use:

function runAtDate(date, func) {
    var now = (new Date()).getTime();
    var then = date.getTime();
    var diff = Math.max((then - now), 0);
    if (diff > 0x7FFFFFFF) //setTimeout limit is MAX_INT32=(2^31-1)
        setTimeout(function() {runAtDate(date, func);}, 0x7FFFFFFF);
    else
        setTimeout(func, diff);
}

Solution 3:

Some explanation here: http://closure-library.googlecode.com/svn/docs/closure_goog_timer_timer.js.source.html

Timeout values too big to fit into a signed 32-bit integer may cause overflow in FF, Safari, and Chrome, resulting in the timeout being scheduled immediately. It makes more sense simply not to schedule these timeouts, since 24.8 days is beyond a reasonable expectation for the browser to stay open.