回答:
これは、32ビットintを使用して遅延を格納するsetTimeoutによるもので、最大許容値は
2147483647
あなたがしようとすると
2147483648
問題が発生します。
私はこれがJS Engineで何らかの内部例外を引き起こし、関数がまったく起動せずにすぐに起動することを推測しているだけです。
49999861776383
(49999861776384
コールバックがすぐに発生する原因)であることがわかりました
49999861776383 % 2147483648 === 2147483647
以下を使用できます。
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日はブラウザーを開いたままにしておくことの妥当な期待を超えているため、これらのタイムアウトをスケジュールしない方が理にかなっています。
setTimeout()
ウェイクアップする日時を計算し、ランダムに定義されたティックでカウンターをデクリメントしないことを望みます... 、少なくとも)
タイマーのノードドキュメントをここで確認してください:https : //nodejs.org/api/timers.html(これはjsでも同じであると仮定します。これは、現在、イベントループベースでこのようなユビキタスな用語であるためです。
要するに:
遅延が2147483647より大きいか1より小さい場合、遅延は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();
Number.MAX_VALUE
実際には整数ではありません。setTimeoutの最大許容値は、おそらく2 ^ 31または2 ^ 32です。試す
parseInt(Number.MAX_VALUE)
1.7976931348623157e + 308の代わりに1を返します。
Number.MAX_VALUE
は整数です。これは整数17976931348623157で、その後に292個のゼロが続きます。その理由のparseInt
リターンは1
、それが最初の文字列に引数を変換し、左から右に文字列を検索するためです。.
(数値ではない)を見つけるとすぐに停止します。
Number.isInteger(foo)
。ただし、まだサポートされていないため、Math.round(foo) === foo
代わりに使用できます。
Number.MAX_VALUE
は、整数ではなくdouble
です。つまり、JavaScriptで32ビットの整数を保存するために使用されるため、doubleは整数を表すことができます。
Number.MAX_VALUE
、整数ではありません。しかし、「整数」によって「整数」の精神的概念を意味する場合、それは整数です。JavaScriptでは、すべての数値が64ビット浮動小数点であるため、「整数」の精神的な概念の定義を使用するのが一般的です。
Number.MAX_SAFE_INTEGER
ますが、ここで探している数でもありません。
delay >>> 0
ことが発生するため、渡される遅延はゼロです。どちらにしても、遅延が32ビットの符号なし整数として格納されるという事実は、この動作を説明しています。ありがとう!