このテスト を使用してsetTimeout
の精度をテストしていました。予想どおり、setTimeout
はあまり正確ではありませんが、ほとんどのアプライアンスでは劇的に不正確ではありません。ここでChromeでテストを実行し、バックグラウンドタブで実行するようにすると(別のタブに切り替えてそこを参照します)、テストに戻って結果を検査します(テストが終了した場合)それらは劇的に変化しています。タイムアウトがずっと遅くなっているようです。 FF4またはIE9でテストしたところ、これは発生しませんでした。
したがって、Chromeは、フォーカスのないタブでJavaScriptの実行を一時停止するか、少なくとも遅くするように見えます。この件については、ネット上で多くを見つけることができなかった。たとえば、XHR呼び出しとsetInterval
を使用してサーバー上で定期的にチェックするなど、バックグラウンドタスクを実行できないことを意味します(setInterval
に対して同じ動作が見られると思われる場合は、私と一緒です)。
誰もこれに遭遇しましたか?この一時停止/スローダウンの回避策はありますか?それをバグと呼びますか?
私は最近これについて尋ねましたが、これは設計上の動作です。タブが非アクティブの場合、最大で毎秒1回のみ関数が呼び出されます。 コード変更 です。
おそらくこれは助けになります: Chromeでタブが非アクティブなときにsetIntervalを動作させるにはどうすればよいですか?
TL; DR:使用Web Workers.
Web Workerは別のプロセスで実行され、速度が低下しないため、Web Workerを使用するソリューションがあります。
コードを変更せずに使用できる小さなスクリプトを作成しました-関数setTimeout、clearTimeout、setInterval、clearIntervalをオーバーライドするだけです
すべてのコードの前にそれを含めるだけです
〜空の音を再生すると、ブラウザはパフォーマンスを維持するように強制されます-このコメントを読んだ後、私はそれを発見しました: タブがアクティブでない場合でもChromeでJavaScriptを通常の速度で実行する方法?
WebSocketを使用するブラウザゲームにはオンデマンドで無制限のパフォーマンスが必要なので、WebSocketを使用しても無制限のパフォーマンスが保証されないことを経験から知っていますが、テストからはオーディオファイルを再生することで確実になりそう
この目的のために作成した2つの空のオーディオループは次のとおりです。商業的に自由に使用できます: http://adventure.land/sounds/loops/empty_loop_for_js_performance.ogghttp://adventure.land/sounds/loops/empty_loop_for_js_performance.wav
(それらには-58dbノイズが含まれ、-60dbは機能しません)
ユーザーの要求に応じて、Howler.jsで再生します: https://github.com/goldfire/howler.js
function performance_trick()
{
if(sounds.empty) return sounds.empty.play();
sounds.empty = new Howl({
src: ['/sounds/loops/empty_loop_for_js_performance.ogg','/sounds/loops/empty_loop_for_js_performance.wav'],
volume:0.5,
autoplay: true, loop: true,
});
}
デフォルトで完全なJavaScriptパフォーマンスをオン/オフする組み込みメソッドがないのは残念ですが、暗号マイナーはプロンプトなしでWeb Workersを使用してすべてのコンピューティングスレッドをハイジャックできます:|
worker-interval npmパッケージをリリースしました。このパッケージは、Chrome、Firefox、IEの非アクティブなタブでWeb-Workersを使用して非アクティブなタブで稼働を維持するsetIntervalおよびclearInterval実装です。
最新のブラウザ(Chrome、Firefox、IE)のほとんど、間隔(ウィンドウタイマー)は、非アクティブなタブで1秒に1回よりも頻繁に起動しないように制限されています。
詳細については、をご覧ください。
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval
JQueryコアを1.9.1に更新し、非アクティブなタブの間隔の不一致を解決しました。最初にそれを試してから、他のコードオーバーライドオプションを調べます。
現在のミリ秒を取得し、それが関数が作成されたミリ秒と比較する私のソリューションです。間隔については、関数を実行するときにミリ秒を更新します。 IDで間隔/タイムアウトを取得することもできます。
<script>
var nowMillisTimeout = [];
var timeout = [];
var nowMillisInterval = [];
var interval = [];
function getCurrentMillis(){
var d = new Date();
var now = d.getHours()+""+d.getMinutes()+""+d.getSeconds()+""+d.getMilliseconds();
return now;
}
function setAccurateTimeout(callbackfunction, millis, id=0){
nowMillisTimeout[id] = getCurrentMillis();
timeout[id] = setInterval(function(){ var now = getCurrentMillis(); if(now >= (+nowMillisTimeout[id] + +millis)){callbackfunction.call(); clearInterval(timeout[id]);} }, 10);
}
function setAccurateInterval(callbackfunction, millis, id=0){
nowMillisInterval[id] = getCurrentMillis();
interval[id] = setInterval(function(){ var now = getCurrentMillis(); if(now >= (+nowMillisInterval[id] + +millis)){callbackfunction.call(); nowMillisInterval[id] = getCurrentMillis();} }, 10);
}
//usage
setAccurateTimeout(function(){ console.log('test timeout'); }, 1000, 1);
setAccurateInterval(function(){ console.log('test interval'); }, 1000, 1);
</script>