HTML 5フロントエンドチュートリアル共有:JavaScriptタイマ

3220 ワード

JSのタイマーは現在3つあります.settimmeout、setInterval、setImmediateです.
タイマも非同期タスクであり、通常、ブラウザには独立したタイマモジュールがあり、タイマの遅延時間はタイマモジュールによって管理され、あるタイマが実行可能な状態になると、メインスレッドキューに追加されます.
JSタイマーは非常に実用的で、アニメーションを作るのに必ず使ったことがあり、最もよく使われる非同期モデルの一つでもあります.
時々奇妙な問題があり、settimeout(fn,0)(以下settimeout(0))を1つ加えると解決します.しかし、タイマー自体に慣れていないと、奇妙な問題も発生します.
setTimeout
settimeout(fn,x)は、xミリ秒遅延後にfnが実行されることを示す.
使用するときはあまり期待を信じないでください.遅延時間は厳密にはxミリ秒より大きく、その時のJSの実行状況によって大きくなります.
また、複数のタイマがタイムリーにクリアされないと、干渉が発生し、遅延時間がよりつかめなくなる.したがって、タイマーが実行されているかどうかにかかわらず、不要なタイマーをタイムリーにクリアするのは良い習慣です.
HTML 5仕様では、最小遅延時間が4 ms未満であってはならず、すなわちxが4未満であれば4として扱われる.ただし、Chromeは1 ms、IE 11/Edgeは4 msなど、ブラウザによって実装が異なります.
settimeoutに登録されている関数fnはブラウザのタイマモジュールに渡されて管理され、遅延時間になるとfnがメインプロセス実行キューに追加され、キューの前に実行済みのコードがある場合は、fnまで実行するのに少し時間がかかるため、実際の遅延時間は設定よりも長くなります.fnの前にちょうどスーパーサイクルがあるように、遅延時間は少しではありません.
(function testSetTimeout() {
const label = 'setTimeout';
console.time(label);
setTimeout(() => {
console.timeEnd(label);
}, 10);
for(let i = 0; i < 100000000; i++) {}
})();
結果:settimeout:335.187 ms、10 msをはるかに超えた.
setInterval
setIntervalの実装メカニズムはsetTimeoutと同様であるが,setIntervalは繰り返し実行される.
setInterval(fn,100)では、前回のfnの実行が完了してから100 msを過ぎて次のfnの実行が開始されたわけではないというエラーが発生しやすい.実際、setIntervalは前回のfnの実行結果にかかわらず、100 msごとにfnをプライマリスレッドキューに入れるが、2回のfnの間の具体的な間隔はどのくらいであるかは定かではなく、setTimeoutの実際の遅延時間と同様に、JSの実行状況と関係がある.
(function testSetInterval() {
let i = 0;
const start = Date.now();
const timer = setInterval(() => {
i += 1;
i === 5 && clearInterval(timer);
console.log(`第${i}次開始`,Date.now()−start);
for(let i = 0; i < 100000000; i++) {}
console.log(`第${i}次終了`,Date.now()−start);
}, 100);
})();
しゅつりょく
1
2
3
4
5
6
7
8
9
10
1回目から100
1回目の終了
1089
2回目スタート1091
2回目の終了
1396
第3回スタート1396
3回目の終了
1701
第4回スタート1701
4回目の終了
2004
第5回開始2004
5回目の終了
2307
fnの実行時間は毎回長いが,次は前回の実行が完了してから100 msを過ぎてから実行を開始するものではなく,実際にはとっくにキューに待っていることがわかる.
またsetIntervalのコールバック関数の実行時間が遅延時間を超えると,時間間隔が全く見えなくなることが分かる.
settimeoutとsetIntervalが100 ms遅延した後に実行される場合、先に登録した人はコールバック関数を実行します.
setImmediate
これは比較的新しいタイマーで、現在IE 11/Edgeサポート、Nodejsサポート、Chromeサポート、他のブラウザはテストされていません.
API名から見るとsettimmeout(0)を連想しやすいが、setImmediateはsettimmeout(0)の代替版であるべきである.
IE 11/EdgeではsetImmediate遅延は1 ms以内であり、setTimeoutでは最低4 msの遅延があるため、setImmediateはsetTimeout(0)よりも早くコールバック関数を実行する.ただし、Nodejsでは、Nodejsのイベントループとブラウザのわずかな違いのため、どちらが先に実行するかは可能です.
(function testSetImmediate() {
const label = 'setImmediate';
console.time(label);
setImmediate(() => {

console.timeEnd(label);
});
})();
Edge出力:setImmediate:0.555ミリ秒
明らかにsetImmediateは,コードを次のイベントループで実行することを保証するために設計されており,従来setTimeout(0)のような信頼できない方法は失われていた.
まとめ:
以上の内容はすべて資料を調べて得たもので、私たちは現在1つのsetIntervalタイマーしか知らない.興味があれば調べてみてください.