在将大毫秒值传递给setTimeout()
. 例如,
setTimeout(some_callback, Number.MAX_VALUE);
和
setTimeout(some_callback, Infinity);
两者都导致some_callback
几乎立即运行,就好像我已经通过0
而不是大量作为延迟。
为什么会发生这种情况?
在将大毫秒值传递给setTimeout()
. 例如,
setTimeout(some_callback, Number.MAX_VALUE);
和
setTimeout(some_callback, Infinity);
两者都导致some_callback
几乎立即运行,就好像我已经通过0
而不是大量作为延迟。
为什么会发生这种情况?
这是由于 setTimeout 使用 32 位 int 来存储延迟,因此允许的最大值为
2147483647
如果你试试
2147483648
你的问题发生了。
我只能假设这是在 JS 引擎中导致某种形式的内部异常并导致函数立即触发而不是根本不触发。
您可以使用:
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);
}
这里有一些解释:http : //closure-library.googlecode.com/svn/docs/closure_goog_timer_timer.js.source.html
超时值太大而无法放入有符号的 32 位整数可能会导致 FF、Safari 和 Chrome 中的溢出,从而导致立即安排超时。不安排这些超时更有意义,因为 24.8 天超出了浏览器保持打开状态的合理预期。
在此处查看计时器上的节点文档:https : //nodejs.org/api/timers.html(假设在 js 中也相同,因为它现在在基于事件循环中是如此普遍的术语
简而言之:
当延迟大于 2147483647 或小于 1 时,延迟将设置为 1。
延迟是:
在调用回调之前等待的毫秒数。
似乎您的超时值被默认为这些规则中的意外值,可能吗?
当我尝试自动注销会话过期的用户时,我偶然发现了这一点。我的解决方案是在一天后重置超时,并保留使用 clearTimeout 的功能。
这是一个小原型示例:
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);
}
};
用法:
var timer = new Timer('2018-08-17 14:05:00', function() {
document.location.reload();
});
您可以使用以下stopTimer
方法清除它:
timer.stopTimer();