ホームページ >ウェブフロントエンド >jsチュートリアル >JSブラウザのイベントループの仕組み

JSブラウザのイベントループの仕組み

不言
不言オリジナル
2018-07-07 17:11:441624ブラウズ

この記事では、主に JS ブラウザーのイベント ループの仕組みを紹介します。これは、必要な友人に参考にしていただけるよう、共有します。まず、概念的な内容を理解しましょう。

プロセス、スレッド

    プロセスはシステムによって割り当てられる独立したリソースであり、CPU リソース割り当ての基本単位であり、プロセスは 1 つ以上のスレッドで構成されます。
  • スレッドはプロセスの実行フローであり、CPU のスケジューリングとディスパッチの基本単位であり、同じプロセス内の複数のスレッドがプロセスのリソースを共有します。
  • ブラウザ カーネル

    ブラウザの各タブ ラベルは、独立したプロセスを表します (複数の空白のタブ ラベルが 1 つのプロセスにマージされるため、必ずしもそうではありません)。レンダリング プロセス) は、ブラウザのマルチプロセスの 1 つです。
  • ブラウザカーネルでは複数のスレッドが動作しています。
    • http リクエストが行われると、リクエスト スレッドが開きます。
    • リクエストが完了して結果が得られると、リクエストのコールバック関数がタスクキューに追加され、JSエンジンによる処理を待ちます。
    • ブラウザのタイミング カウンタは JS エンジンによってカウントされないため、ブロックするとタイミングが不正確になります。
    • タイマートリガースレッドを有効にしてタイミングを計測し、タイミングが完了するとタスクキューに追加され、JSエンジンによる処理を待ちます。
    • イベントがトリガー条件を満たしてトリガーされると、スレッドは対応するイベント コールバック関数をタスク キューの最後に追加し、JS エンジンによる処理を待ちます。
    • シングルスレッドの作業。JavaScript スクリプトの解析と実行を担当します。
    • と GUI レンダリング スレッドは相互に排他的です。JS の実行に時間がかかりすぎる場合、ページはブロックされます。
    • ページのレンダリング、HTML、CSS の解析による DOM ツリーの形成などを担当します。このスレッドは、ページが再描画されるか、何らかの操作によってリフローが発生するときに呼び出されます。
    • と JS エンジン スレッドは相互に排他的です。JS エンジン スレッドが動作している場合、GUI レンダリング スレッドは一時停止され、GUI 更新は JS タスク キューに置かれ、JS エンジン スレッドが続行するのを待ちます。アイドル時に実行されます。
    • GUIレンダリングスレッド:
    • JSエンジンスレッド:
    • イベントトリガースレッド:
    • タイマートリガースレッド:
    • httpリクエストスレッド:

JSブラウザのイベントループの仕組みJavaScriptエンジンはシングルスレッドです

JavaScript エンジンはシングルスレッドです。つまり、一度に 1 つのタスクのみを実行でき、他のタスクは実行を待機するためにキューに入れられる必要があります。現在のタスクが完了した後にのみ、次のタスクが実行されます。

Web-Worker API は、主にページのブロックの問題を解決するために HTML5 で提案されていますが、JavaScript のシングルスレッドの性質は変わりません。 Web ワーカーについて学びましょう。

JavaScriptのイベントループ機構

JavaScriptのイベントループ機構はブラウザーとノードのイベントループ機構に分かれており、ブラウザーのイベントループはHTMLで定義された仕様であり、ノードのイベントループはlibuvで実装されています。図書館。ここでの主な焦点はブラウザ部分です。

JavaScript にはメインスレッドと呼び出しスタック (実行スタック) があり、すべてのタスクは呼び出しスタックに配置され、メインスレッドが実行されるのを待ちます。

    JS 呼び出しスタック
  • JS 呼び出しスタックは、後入れ先出しのデータ構造です。関数が呼び出されると、その関数はスタックの先頭に追加され、実行が完了すると、スタックがクリアされるまでその関数はスタックの先頭から削除されます。

  • 同期タスク、非同期タスク
  • 単一スレッド内のJavaScriptタスクは、同期タスクと非同期タスクに分けられます。同期タスクはコール スタック内で順番にキューに入れられ、メイン スレッドの実行を待機します。一方、非同期タスクは、非同期結果が利用可能になった後、登録されたコールバック関数をタスク キュー (メッセージ キュー) に追加し、メイン スレッドが実行されるのを待ちます。アイドル、つまりスタック内 クリアされると、スタックに読み込まれ、メインスレッドによる実行を待ちます。タスクキューは先入れ先出しのデータ構造です。

  • イベントループ
  • コールスタック内のすべての同期タスクが実行され、スタックがクリアされた後、この時点でメインスレッドがアイドル状態であることを意味します。順序付けしてスタック実装に配置します。スタックをクリアするたびにタスクキューにタスクがあるかどうかを読み出し、タスクがあれば読み込んで実行するという動作がイベントループを形成します。

JSブラウザのイベントループの仕組み

JSブラウザのイベントループの仕組み

    タイマー
  • タイマーは、指定された時間待機した後、タイマー トリガー スレッドを開始して、読み取りを待機します。実行用のメインスレッド。

    タイマーによって指定された遅延ミリ秒数は、実際には正確ではありません。これは、タイマーは、指定された時間に達した場合にのみイベントをタスク キューに配置し、同期されたタスクと既存のタスク キュー内のイベントが完了するまで待機する必要があるためです。完了後はタイマーイベントを読み込んでメインスレッド上で実行するため、途中で時間がかかるタスクが存在する可能性があり、指定した時刻に実行されることは保証できません。

  • マクロタスク、マイクロタスク

    一般化された同期タスクと非同期タスクに加えて、JavaScript シングルスレッドのタスクはマクロタスクとマイクロタスクに細分化できます。

    マクロタスクには、スクリプト (コード全体)、setTimeout、setInterval、setImmediate、I/O、UI レンダリングが含まれます。

    マイクロタスクには、process.nextTick、Promises、Object.observe、MutationObserver が含まれます。

        console.log(1);
        setTimeout(function() {
            console.log(2);
        })
        var promise = new Promise(function(resolve, reject) {
            console.log(3);
            resolve();
        })
        promise.then(function() {
            console.log(4);
        })
        console.log(5);

    例ではsetTimeoutとPromiseをタスクソースと呼び、異なるタスクソースから登録されたコールバック関数は異なるタスクキューに入れられます。

    マクロタスクとマイクロタスクの概念がわかったところで、JSの実行順序はどうなるのでしょうか?マクロタスクとミクロタスクはどちらを先にすべきでしょうか?

    最初のイベント ループでは、JavaScript エンジンはスクリプト コード全体をマクロタスクとして実行し、実行が完了した後、このループ内にマイクロタスクがあるかどうかを検出し、存在する場合はタスクから読み取ります。すべてのマイクロタスクを実行した後、マクロタスクのタスクキュー内のタスク実行を読み取り、すべてのマイクロタスクを実行します。 JSの実行順序は、各イベントループ内のマクロタスク→マイクロタスクとなります。

    • 上記の例では、最初のイベント ループで、コード全体がマクロ タスクとして実行するためにメイン スレッドに入ります。

    • setTimeoutに遭遇すると、指定された時間が経過するまで待機し、コールバック関数をマクロタスクのタスクキューに入れます。

    • Promise に遭遇したら、then 関数をマイクロタスクのタスクキューに入れます。

    • イベントループ全体が完了した後、マイクロタスクのタスクキューにタスクがあるかどうかを検出し、存在する場合はそれを実行します。

    • 最初のサイクルの結果は、1、3、5、4 として出力されます。

    • 次に、マクロタスクのタスクキューに移動し、マクロタスクを順番に取り出し、メインスレッドが実行できるようにスタックに置きます。そして、このループ内のマクロタスクは、setTimeoutによって登録されたコールバック関数です。このコールバック関数を実行した後、このサイクルにはマイクロタスクがないことがわかり、次のイベント サイクルの準備が整いました。

    • マクロタスクキューに実行すべきタスクがないことが検出された場合、イベントループは終了します。

    • 最終結果は 1,3,5,4,2 です。

    上記がこの記事の全内容です。その他の関連コンテンツについては、PHP 中国語 Web サイトをご覧ください。

    関連する推奨事項:

    JS タイマーとシングルスレッドの非同期機能

以上がJSブラウザのイベントループの仕組みの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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