大きなミリ秒の値をsetTimeout()
に渡すと、予期しない動作に遭遇しました。例えば、
setTimeout(some_callback, Number.MAX_VALUE);
そして
setTimeout(some_callback, Infinity);
両方ともsome_callback
を通過したかのように、すぐに実行されます0
遅延として大きな数の代わりに。
なぜこれが起こるのですか?
これは、setTimeoutが遅延を格納するために32ビットintを使用しているため、許可される最大値は
2147483647
試してみると
2147483648
問題が発生します。
これは、JSエンジンで何らかの形の内部例外を引き起こし、関数がまったく起動するのではなく、すぐに起動することを想定しているだけです。
ここでいくつかの説明: http://closure-library.googlecode.com/svn/docs/closure_goog_timer_timer.js.source.html
タイムアウト値が大きすぎて符号付き32ビット整数に収まらない場合、FF、Safari、Chromeでオーバーフローが発生し、すぐにタイムアウトがスケジュールされる可能性があります。ブラウザが開いたままになるのに24.8日は妥当な予想を超えているため、これらのタイムアウトをスケジュールしない方が簡単です。
次を使用できます。
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);
}
期限切れのセッションでユーザーを自動的にログアウトしようとしたときに、これにつまずきました。私の解決策は、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();
ここでタイマーに関するノードのドキュメントを確認してください: https://nodejs.org/api/timers.html (jsでも同様であると仮定します。ループベース
要するに:
遅延が2147483647より大きいか、1より小さい場合、遅延は1に設定されます
遅延は次のとおりです。
コールバックを呼び出す前に待機するミリ秒数
これらのルールに沿って、タイムアウト値が予期しない値にデフォルト設定されているようです。
コメントはできませんが、すべての人に答えます。符号なしの値を取ります(明らかに負のミリ秒を待つことはできません)。したがって、最大値は「2147483647」なので、より高い値を入力すると0から開始されます。
基本的に遅延= {VALUE}%2147483647。
したがって、2147483648の遅延を使用すると、1ミリ秒になるため、インスタントプロシージャになります。