JavaScript タイマーの仕組み

高洛峰
リリース: 2017-02-04 17:19:14
オリジナル
1379 人が閲覧しました

JavaScript でタイマーについて話すとき、setTimeout() と setInterval() という 2 つの関数を必ず思い浮かべます。この記事では、イベント ループの観点から、両者の動作原理と違いを分析します。

setTimeout()

MDNはsetTimeoutを次のように定義しています:

指定された遅延時間の後に関数を呼び出すか、コードフラグメントを実行します。

構文

setTimeoutの構文は非常に単純で、最初のパラメータはコールバック関数、2番目のパラメータは遅延時間です。この関数は、数値型 ID の一意の識別子を返します。この ID は、タイマーをキャンセルするために、clearTimeout のパラメーターとして使用できます。 :

var timeoutID = window.setTimeout(func, late, [param1, param2, ...]);

setInterval()

MDN は setInterval を次のように定義します:

関数を定期的に呼び出す、またはコードの一部を実行する。

setInterval と setTimeout の使用法は同じであるため、ここにはリストされません。

第二引数(遅延)の説明

JavaScriptのイベントループの仕組み上、第二引数は遅延ミリ秒後にすぐにコールバック関数が実行されるわけではなく、コールバック関数を遅延ミリ秒後に追加しようとします。イベントキュー。実際、この時点で setTimeout と setInterval の処理には違いがあります。

setTimeout: 遅延ミリ秒が経過すると、何があってもコールバック関数がイベント キューに直接追加されます。

setInterval: ミリ秒の遅延後、まずイベント キューにまだ実行されていないコールバック関数 (setInterval のコールバック関数) があるかどうかを確認し、存在する場合はイベント キューにコールバック関数を追加しません。

そのため、コード内に時間のかかるタスクがある場合、タイマーは想定どおりに動作しません。

理解するための例を通して

次のコードは当初、100ms と 200ms でコールバック関数を呼び出せることを期待していました (つまり、100ms を待っているだけです):

var timerStart1 = now();

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 () {

console.log('1回目のsetTimeoutコールバック実行待機時間:', now() - timerStart1);

var timerStart2 = now();

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 ミリ秒待機します。

次の図に要約できます:

javascript 定时器工作原理

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 タイマーの実行原理の簡単な分析です。記事内に不適切な記述がございましたら、コメントにてご指摘ください。

JavaScript タイマーの動作原理に関連するその他の記事については、PHP 中国語 Web サイトに注目してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート