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

JavascriptSettimeout

Javascript Problem Overview


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?

Javascript Solutions


Solution 1 - Javascript

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 - Javascript

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 - Javascript

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.

Solution 4 - Javascript

Check out the node doc on Timers here: https://nodejs.org/api/timers.html (assuming same across js as well since it's such an ubiquitous term now in event loop based

In short:

When delay is larger than 2147483647 or less than 1, the delay will be set to 1.

and delay is:

The number of milliseconds to wait before calling the callback.

Seems like your timeout value is being defaulted to an unexpected value along these rules, possibly?

Solution 5 - Javascript

Can't comment but to answer all the people. It takes unsigned value ( you can't wait negative milliseconds obviously ) So since max value is "2147483647" when you enter a higher value it start going from 0.

Basically delay = {VALUE} % 2147483647.

So using delay of 2147483648 would make it 1 millisecond, therefore, instant proc.

Solution 6 - Javascript

I stumbled on this when I tried to automatically logout a user with an expired session. My solution was to just reset the timeout after one day, and keep the functionality to use clearTimeout.

Here is a little prototype example:

Timer = function(execTime, callback) {
	if(!(execTime instanceof Date)) {
		execTime = new Date(execTime);
	}

	this.execTime = execTime;
	this.callback = callback;

	this.init();
};

Timer.prototype = {

	callback: null,
	execTime: null,

	_timeout : null,

	/**
	 * Initialize and start timer
	 */
	init : function() {
		this.checkTimer();
	},

	/**
	 * Get the time of the callback execution should happen
	 */
	getExecTime : function() {
		return this.execTime;
	},

	/**
	 * Checks the current time with the execute time and executes callback accordingly
	 */
	checkTimer : function() {
		clearTimeout(this._timeout);

		var now = new Date();
		var ms = this.getExecTime().getTime() - now.getTime();

		/**
		 * Check if timer has expired
		 */
		if(ms <= 0) {
			this.callback(this);

			return false;
		}

		/**
		 * Check if ms is more than one day, then revered to one day
		 */
		var max = (86400 * 1000);
		if(ms > max) {
			ms = max;
		}

		/**
		 * Otherwise set timeout
		 */
		this._timeout = setTimeout(function(self) {
			self.checkTimer();
		}, ms, this);
	},

	/**
	 * Stops the timeout
	 */
	stopTimer : function() {
		clearTimeout(this._timeout);
	}
};

Usage:

var timer = new Timer('2018-08-17 14:05:00', function() {
	document.location.reload();
});

And you may clear it with the stopTimer method:

timer.stopTimer();

Solution 7 - Javascript

Number.MAX_VALUE

is actually not an integer. The maximum allowable value for setTimeout is likely 2^31 or 2^32. Try

parseInt(Number.MAX_VALUE) 

and you get 1 back instead of 1.7976931348623157e+308.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMatt BallView Question on Stackoverflow
Solution 1 - JavascriptOneSHOTView Answer on Stackoverflow
Solution 2 - JavascriptRonenView Answer on Stackoverflow
Solution 3 - JavascriptwarpechView Answer on Stackoverflow
Solution 4 - JavascriptSillyGillyView Answer on Stackoverflow
Solution 5 - JavascriptKYGASView Answer on Stackoverflow
Solution 6 - JavascriptTimView Answer on Stackoverflow
Solution 7 - JavascriptOsmundView Answer on Stackoverflow