Javascript 为什么 setTimeout() 对于大的毫秒延迟值“中断”?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3468607/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does setTimeout() "break" for large millisecond delay values?
提问by Matt Ball
I came across some unexpected behavior when passing a large millisecond value to setTimeout(). For instance,
在将大毫秒值传递给setTimeout(). 例如,
setTimeout(some_callback, Number.MAX_VALUE);
and
和
setTimeout(some_callback, Infinity);
both cause some_callbackto be run almost immediately, as if I'd passed 0instead of a large number as the delay.
两者都导致some_callback几乎立即运行,就好像我已经通过0而不是大量作为延迟。
Why does this happen?
为什么会发生这种情况?
回答by OneSHOT
This is due to setTimeout using a 32 bit int to store the delay so the max value allowed would be
这是由于 setTimeout 使用 32 位 int 来存储延迟,因此允许的最大值为
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.
我只能假设这是在 JS 引擎中导致某种形式的内部异常并导致函数立即触发而不是根本不触发。
回答by warpech
Some explanation here: http://closure-library.googlecode.com/svn/docs/closure_goog_timer_timer.js.source.html
这里有一些解释: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.
超时值太大而无法放入有符号的 32 位整数可能会导致 FF、Safari 和 Chrome 中的溢出,从而导致立即安排超时。不安排这些超时更有意义,因为 24.8 天超出了浏览器保持打开状态的合理预期。
回答by Ronen
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);
}
回答by SillyGilly
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
在此处查看计时器上的节点文档:https: //nodejs.org/api/timers.html(假设在 js 中也是如此,因为它现在在基于事件循环中是一个无处不在的术语
In short:
简而言之:
When delay is larger than 2147483647 or less than 1, the delay will be set to 1.
当延迟大于 2147483647 或小于 1 时,延迟将设置为 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?
似乎您的超时值被默认为这些规则中的意外值,可能吗?
回答by Tim
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.
当我尝试自动注销会话过期的用户时,我偶然发现了这一点。我的解决方案是在一天后重置超时,并保留使用 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 stopTimermethod:
您可以使用以下stopTimer方法清除它:
timer.stopTimer();
回答by KYGAS
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.
不能评论,只能回答所有人。它采用无符号值(显然您不能等待负毫秒)因此,由于最大值为“2147483647”,因此当您输入更高的值时,它从 0 开始。
Basically delay = {VALUE} % 2147483647.
基本上延迟 = {VALUE} % 2147483647。
So using delay of 2147483648 would make it 1 millisecond, therefore, instant proc.
因此,使用 2147483648 的延迟将使其变为 1 毫秒,因此,即时过程。
回答by Osmund
Number.MAX_VALUE
is actually not an integer. The maximum allowable value for setTimeout is likely 2^31 or 2^32. Try
实际上不是整数。setTimeout 的最大允许值可能是 2^31 或 2^32。尝试
parseInt(Number.MAX_VALUE)
and you get 1 back instead of 1.7976931348623157e+308.
你会得到 1 而不是 1.7976931348623157e+308。

