ホームページ > 記事 > ウェブフロントエンド > JavaScriptのイベントループの仕組みを詳しく解説 - 第1回
JavaScript のイベント ループの仕組み。多くの記事では、JavaScript のイベントは同期タスクと非同期タスクに分けられ、同期タスクに遭遇した場合は実行スタックに配置され、非同期タスクに遭遇した場合には配置されるとだけ書かれています。タスク キュー内のイベントを実行する前に、実行スタックが完了するまで待機します。この記事はとても良いです!一緒に見ましょう!早速本題に入りましょう!
関数呼び出しスタックとタスクキュー
JavaScriptには、メインスレッドのメインプロセスと呼び出しスタック(呼び出しスタック)があります。呼び出しスタック内のタスクを処理するとき、他のものはすべて待機する必要があります。実行中に setTimeout などの非同期操作が発生すると、setTimeout で指定された遅延実行時間に達すると、ブラウザの他のモジュール (Webkit を例に挙げると、Webcore モジュール) に処理が渡されます。 コールバック関数)がタスクキューに入れられます。一般に、異なる非同期タスクのコールバック関数は異なるタスク キューに配置されます。コールスタック内のすべてのタスクが実行されるまで待ってから、タスクキュー内のタスク(コールバック関数)を実行します。
フィリップ・ロバーツのスピーチ「助けて、イベントループにはまってしまいました」の画像を使用すると、
上の画像では、コールスタックでDOM操作とajaxリクエストが発生し、setTimeoutなどが発生しています。 WebAPI は、Javasctipt 実行エンジンに加えて、ブラウザ カーネルの他のモジュールに渡されて処理されます。Webkit カーネルには、Webcore モジュールと呼ばれる重要なモジュールがあります。図の WebAPI で示されている 3 つの API について、Webcore は、基礎となる実装を処理するために、それぞれ DOM バインディング、ネットワーク、およびタイマー モジュールを提供します。これらのモジュールがこれらの操作の処理を完了したら、コールバック関数をタスク キューに入れ、スタック内のタスクが実行されるのを待ってから、タスク キュー内のコールバック関数を実行します。
setTimeout からイベント ループ メカニズムを確認する
以下では、Philip Roberts の講演からの例を使用して、イベント ループ メカニズムが setTimeout を実行する方法を説明します。
まず、main() 関数の実行コンテキストがスタックにプッシュされます
その後、コードが実行され、console.log('Hi') が発生します。 ') がスタックにプッシュされ、console.log メソッドが Webkit カーネルでサポートされる通常のメソッドであるため、log('Hi') メソッドがすぐに実行されます。このとき「Hi」が出力されます。
setTimeout が発生すると、実行エンジンはそれをスタックに追加します。
setTimeout が前述の WebAPI の API であることがコール スタックで判明したため、スタックからポップした後、遅延実行関数はブラウザのタイマー モジュールに引き渡されて処理されます。
タイマーモジュールは遅延実行関数を処理します。このとき、実行エンジンは実行してログ('SJS')をスタックに追加し、'SJS'を出力します。
タイマーモジュールの遅延メソッドで指定された時間が経過すると、タスクキューに入れられます。この時点で、コールスタック内のすべてのタスクが実行されます。
コールスタック内のタスクが実行された後、実行エンジンは、実行タスクキュー内に実行する必要があるコールバック関数があるかどうかを確認します。ここでの cb 関数は、実行エンジンによってコール スタックに追加され、内部のコードを実行して「そこに」出力します。実行が完了するまで待ってから、スタックからポップします。
概要
上記のプロセスは、前の図で説明した他の API やその他の非同期操作と同様に、ブラウザーが setTimeout に遭遇したときにそれを実行する方法を説明しています。
上記の内容を要約すると、主なポイントは次のとおりです:
1. すべてのコードは、関数呼び出しスタックからの呼び出しを通じて実行する必要があります。
2. 上記の API が発生すると、処理のためにブラウザー カーネル内の他のモジュールに渡されます。
3. コールバック関数はタスクキューに格納されます。
4. コールスタック内のタスクが実行されるまで待ってから、タスクキュー内のタスクを実行します。
テスト
for (var i = 0; i < 5; i++) { setTimeout(function() { console.log(new Date, i); }, 1000); } console.log(new Date, i);
応募者の80%が不合格となったJS面接の質問に関するインターネット上の最近の記事からこのコードを見つけました。次に、このコードがどのように出力されるかを分析してみましょう。前回の記事:
40% の人は、5 -> 5,5,5,5,5、つまり、最初の 5 が直接出力され、1 秒後に 5 5 が出力されます。1. まず、i=0 の場合、条件が満たされ、実行スタックはループ本体内のコードを実行し、スタックからポップした後、遅延実行関数をタイマーに渡します。処理用のモジュール。 2. i=1,2,3,4 の場合、状況は i=0 の場合と同じなので、タイマーモジュールには同じ遅延実行関数が 5 つあります。
3. i=5の場合は条件を満たさないので
forループが終了し、console.log(new Date, i)がスタックにプッシュされます。したがって、出力は 5 になります。
4. この時点で1秒が経過し、タイマーモジュールは登録順に5つのコールバック関数をタスクキューに返します。 5. 実行エンジンはタスクキュー内の関数を実行します。このとき、5 つの関数がスタックにプッシュされてからポップアウトされます。したがって、5 つの 5 がほぼ同時に出力されます。
6. したがって、最初の 5 を出力した後の 1 秒の待ち時間は、実際には 1 秒だけです。この 1 秒の時間は、タイマー モジュールがコールバック関数をタスク キューに渡す前に待機する必要がある指定された 1 秒の時間です。実行スタックが完了したら、タスク キュー内の 5 つのコールバック関数を実行します。この期間中は 1 秒待つ必要はありません。したがって、出力ステータスは 5 -> 5,5,5,5,5 になります。つまり、最初の 5 が直接出力され、1 の後に 5 が出力されます。
質問
を参照してください。イベント ループのメカニズムについては大体理解できましたが、よく考えてみると、検討する価値のある問題がまだいくつかあります。 以下は栗を通して説明されています: (function test() {
setTimeout(function() {console.log(4)}, 0);
new Promise(function executor(resolve) {
console.log(1);
for( var i=0 ; i<10000 ; i++ ) {
i == 9999 && resolve();
}
console.log(2);
}).then(function() {
console.log(5);
});
console.log(3);
})()
このコードには追加の Promise があり、次の質問について考えることができます:
1. Promise のタスクは別のタスク キューに配置され、 setTimeoutのタスク キューとPromiseタスクキューの実行順序は何ですか?
jsイベントループメカニズムの分析例
以上がJavaScriptのイベントループの仕組みを詳しく解説 - 第1回の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。