ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScriptのイベントループ機構例を詳しく解説

JavaScriptのイベントループ機構例を詳しく解説

小云云
小云云オリジナル
2018-02-27 14:02:572141ブラウズ

JavaScript にはメインスレッドのメインプロセスと呼び出しスタック (呼び出しスタック) があり、呼び出しスタック内のタスクを処理するとき、他のものはすべて待機する必要があります。実行中に setTimeout などの非同期操作が発生すると、setTimeout で指定された遅延実行時間に達すると、それらの操作はブラウザーの他のモジュール (Webkit を例として、Webcore モジュール) に引き渡されて処理されます。 (コールバック関数) がタスクキューに入れられます。一般に、異なる非同期タスクのコールバック関数は異なるタスク キューに配置されます。コールスタック内のすべてのタスクが実行されるまで待ってから、タスクキュー内のタスク(コールバック関数)を実行します。


上の図では、コール スタックが DOM 操作、Ajax リクエスト、setTimeout、その他の WebAPI に遭遇すると、処理のためにブラウザ カーネルの他のモジュールに渡されます。Webkit カーネルは Javasctipt の実行の外部にあります。重要なモジュールは Webcore モジュールです。図の WebAPI で示されている 3 つの API について、Webcore は、基礎となる実装を処理するために、それぞれ DOM バインディング、ネットワーク、およびタイマー モジュールを提供します。これらのモジュールがこれらの操作の処理を完了したら、コールバック関数をタスク キューに入れ、スタック内のタスクが実行されるのを待ってから、タスク キュー内のコールバック関数を実行します。

setTimeout からイベント ループ メカニズムを確認する

以下では、Philip Roberts の講演の例を使用して、イベント ループ メカニズムが setTimeout を実行する方法を説明します。


まず、main() 関数の実行コンテキストがスタックにプッシュされます


その後、コードが実行され、console.log('Hi') が検出されます。 log('Hi') はスタック、コンソールにプッシュされます。 .log メソッドは Webkit カーネルによってサポートされる通常のメソッドであるため、log('Hi') メソッドはすぐに実行されます。このとき「Hi」が出力されます。


setTimeout が発生すると、実行エンジンはそれをスタックに追加します。


コールスタックにより、setTimeout が前述の WebAPI の API であることが判明したため、スタックからポップした後、遅延実行関数はブラウザのタイマー モジュールに渡されて処理されます。


タイマーモジュールは、遅延実行関数を処理します。このとき、実行エンジンは実行され、log(‘SJS’)をスタックに追加し、‘SJS’を出力します。


タイマーモジュールの遅延メソッドで指定された時間が経過すると、タスクキューに入れられます。この時点で、コールスタック内のすべてのタスクが実行されます。



コールスタック内のタスクが実行された後、実行エンジンは、実行タスクキュー内に実行する必要があるコールバック関数があるかどうかを確認します。ここでの cb 関数は、実行エンジンによってコール スタックに追加され、内部のコードを実行して「そこに」出力します。実行が完了するまで待ってから、スタックからポップします。

概要

  • すべてのコードは、関数呼び出しスタックからの呼び出しを通じて実行する必要があります。

  • 上記の API が発生すると、処理のためにブラウザ カーネル内の他のモジュールに渡されます。

  • タスクキューにはコールバック関数が格納されます。

  • コールスタック内のタスクが実行されるまで待ってから、戻ってタスクキュー内のタスクを実行します。

テスト

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の場合、条件が満たされ、実行スタックはループ本体内のコードを実行し、setTimeoutになったことをスタックからポップした後、遅延実行関数を引き継ぎます。処理のためにタイマーモジュールに送信されます。

  2. i=1,2,3,4 の場合、状況は i=0 の場合と同じなので、タイマーモジュールには同じ遅延実行関数が 5 つあります。

  3. i=5の場合は条件を満たさないのでforループが終了しconsole.log(new Date, i)がスタックにプッシュされます。この時点でiは5になっています。したがって、出力は 5 になります。

  4. この時点で1秒が経過し、タイマーモジュールは登録順に5つのコールバック関数をタスクキューに返します。

  5. 実行エンジンはタスクキュー内の関数を実行します。5つの関数が実行のためにスタックにプッシュされ、その後ポップアウトされます。このとき、iは5になります。したがって、5 つの 5 がほぼ同時に出力されます。

  6. つまり、最初の 5 を出力した後の 1 秒の待ち時間は、実際にはわずか 1 秒です。この 1 秒の時間は、タイマー モジュールがコールバック関数をタスク キューに渡す前に待機する必要がある、指定された 1 秒の時間です。実行スタックが完了したら、タスク キュー内の 5 つのコールバック関数を実行します。この期間中は 1 秒待つ必要はありません。したがって、出力ステータスは 5 -> 5,5,5,5,5 になります。つまり、最初の 5 が直接出力され、1 の後に 5 が出力されます。 jsイベントループの仕組み サンプル分析

以上がJavaScriptのイベントループ機構例を詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。