JavaScript でタイマーについて話すとき、setTimeout() と setInterval() という 2 つの関数を必ず思い浮かべます。この記事では、イベント ループの観点から、両者の動作原理と違いを分析します。
setTimeout()
MDNはsetTimeoutを次のように定義しています:
指定された遅延時間の後に関数を呼び出すか、コードフラグメントを実行します。
構文
setTimeoutの構文は非常に単純で、最初のパラメータはコールバック関数、2番目のパラメータは遅延時間です。この関数は、数値型 ID の一意の識別子を返します。この ID は、タイマーをキャンセルするために、clearTimeout のパラメーターとして使用できます。 :
var timeoutID = window.setTimeout(func, late, [param1, param2, ...]);
setInterval()
MDN は setInterval を次のように定義します:
setTimeout(function ( ) {
console.log('最初の setTimeout コールバック実行待ち時間:', now() - timerStart1); var timerStart2 = now(); setTimeout(function () {
console.log('2 番目の setTimeout callback 実行待機時間: ', now() - timerStart2);
}, 100);
}, 100);
// 出力:
// 1 回目の setTimeout コールバック実行待機時間: 106
// 2 回目の setTimeout コールバック実行待機time: 107
この結果は希望どおりに見えますが、時間のかかるタスクをコードに追加すると、結果は期待したものと異なります。
var timerStart1 = now();
setTimeout(function () {
setTimeout(function () {
console.log('2回目のsetTimeoutコールバック実行待機時間) time:', now() - timerStart2);
}, 100);
heavyTask(); // 時間のかかるタスク
}, 100); / 時間のかかるタスク
console.log('heavyTask には時間がかかります:', now() -oopStart);
function HeavyTask() {
var s = now ();
while(now() - s }
}
function now () {
return new Date();
}
// 出力:
// HeavyTask 消費時間: 1015
// 最初の setTimeout コールバック実行待ち時間: 1018
// 2 番目の setTimeout コールバック実行待ち時間: 1000
時間のかかるタスクの存在により、2 つの setTimeout の待機イベントが 100ms ではなくなりました。何が起こったのか説明しましょう:
まず、時間のかかる最初のタスク (heavyTask()) が実行を開始し、完了するまでに約 1000 ミリ秒かかります。
時間のかかるタスクの実行を開始します。100ms 後、最初の setTimeout コールバック関数が実行されると予想されるため、イベント キューに追加されます。ただし、前の時間のかかるタスクはまだ実行されていないため、実行できます。時間のかかるタスクが完了するまで待機しているだけでは実行は開始されないため、結果は次のようになります。 最初の setTimeout コールバック実行待機時間: 1018。
最初の setTimeout コールバックが実行されるとすぐに、2 番目の setTimeout も 100 ミリ秒の遅延後にコールバック関数を実行することが期待されます。ただし、最初の setTimeout には別の時間のかかるタスクがあり、そのプロットは最初のタイマーと同じで、実行を開始する前に 1000 ミリ秒待機します。
setInterval の例を見てみましょう:
var intervalStart = now();
setInterval(function () {
console.log('interval はタイマーを定義してからの時間です:', now() - loopStart );
}, 100);
var ループスタート = now();
heavyTask();
console.log('heavyTask には時間がかかります:', now() -loopStart);
function HeavyTask() {
var s = now();
while(now() - s }
}
function now () {
return new Date();
}
// 出力:
// HeavyTask の消費時間: 1013
//タイマーを定義してからの間隔時間: 1016
//タイマーを定義してからの間隔時間: 1123
//タイマーを定義してからの間隔時間: 1224
上記のコードでは、100ms ごとに a を入力することを期待しています。ログ。 setTimeout と比較すると、setInterval は、イベント キューにコールバック関数を追加する準備をするときに、キューに未実行のコールバックがあるかどうかを判断します。ある場合は、コールバック関数をキューに追加しません。 それ以外の場合、複数のコールバックが同時に実行されます。
それは次の図に要約できます:
要約
上記は、JavaScript をより深く理解するのに役立つことを期待して、JavaScript タイマーの実行原理の簡単な分析です。記事内に不適切な記述がございましたら、コメントにてご指摘ください。
JavaScript タイマーの動作原理に関連するその他の記事については、PHP 中国語 Web サイトに注目してください。