JavaScript単一スレッド非同期の背後にあるイベントサイクル機構

5942 ワード

この文章はだいぶ長引いたような気がします.
本文はここから始まります.
JavaScriptに対してぼんやりとした印象があります.シングルスレッドが非同期です.本文では主にJavaScriptはどのように運行されていますか?その前に、これらの概念を整理してみましょう.
基本概念
スレッドとプロセス
プロセス(Process)は、システムリソースの割り当てとスケジューリングのユニットである.実行しているプログラムは一つのプロセスに対応しています.プロセスは、実行中のプログラムとプログラムが使用するメモリとシステムリソースを含んでいます.シングルコアCPUであれば、同じ時間内にあり、一つのプロセスだけが実行されます.しかし、単一のコアCPUは、複数のタスクを同時に実行することができます.これは2つのプロセス(マルチプロセス)を開いていますが、動作のメカニズムはすぐに歌を再生したり、あなたのタイピングに応答したりしますが、CPUの切り替えのスピードが速いので、まったく感じられないです.この2つのプロセスは同時に実行されていると思います.プロセス間のリソース分離です.
そのスレッドは何ですか?スレッドはプロセスの実行者で、一つのプロセスは少なくともスレッド(メインスレッド)を開いてもいいし、複数のスレッドを開いてもいいです.例えば網易雲音楽はオーディオを流しながら歌詞を表示します.マルチプロセスの実行は、つまりプロセスのスレッドを介して実行されます.プロセスのスレッドは共有リソースです.複数のスレッドが同じリソースを同時に操作すると、資源の奪い合いが発生します.これはまた別の問題です.
並行と合併
パラレルとは、プログラムの動作状態を指し、同じ時間にいくつかのことが並列して処理されています.一つのスレッドは同じ時間に一つのことしか処理できないので、複数のスレッドが同時に複数のことを実行する必要があります.
併発とはプログラムの設計構造を指し、同じ時間に複数の事柄を交互に処理することができる.大事なのは、ある時間に一つだけのことが実行されていることです.例えば、シングルコアCPUがマルチタスク実行を実現するプロセスは同時です.
同期と非同期
同期非同期とは、プログラムの動作のことです.同期(Synchronous)はプログラムが起動した時、結果が戻ってくるまで待っています.結果がないと戻ってこないです.つまり、同期は、使用者が起動を待っている.
非同期は呼び出しを出してすぐに戻ってきますが、結果はすぐには戻りません.调节者は自発的に待つ必要はなく、调节された者が结果を得たら、积极的に调节者に通知します.
例えば、ミルクティーのお店で飲み物を買います.同期とは、お客さんが要求を言ってから、従業員が飲み物を作ってくれるのをずっと待っています.お客さんが自分で注文した飲み物を持ってから出発します.そして次の顧客は上記のプロセスを繰り返します.异歩とは、お客さんが先に列に並んで注文して、注文した後に伝票を持って、従業員ができたら番号を呼びます.あなたに呼んでもらえばいいです.
したがって、スレッドは同期非同期と直接関係がなく、シングルスレッドでも非同期化が可能です.実現の方式については、以下に具体的に説明します.
渋滞と渋滞
渋滞と渋滞は待機状態のことです.ブロッキング(Blocking)とは、待ち時間中にスレッドを呼び出すことを指します.(CPUリソースは他の場所に割り当てられました).
ブロッキングではないということは、待ち時間の間にCPUリソースがスレッド内にあり、スレッドは他のこともできます.
先ほど並んで飲み物を買いましたが、渋滞は待っている時には何もできません.渋滞ではなく、待っている時に他のことをしてもいいです.
したがって、同期はブロックしてもいいし、ブロックしなくてもいいし、非同期はブロックしてもいいし、ブロックしなくてもいいです.
単スレッドのJS
大体上記の概念を理解してから、単スレッドと非同期は矛盾していないことが分かります.JSはどうやって実行しますか?JSは実は1つの言語で、1スレッドと言いますか?それともマルチスレッドは具体的な運行環境を結び付けなければなりません.JSの運行は普通ブラウザで行われます.具体的にはJSエンジンで解析して実行します.これからブラウザについて詳しく調べてみます.
ブラウザ
現在最も人気のあるブラウザはChrome、IE、Safari、FireFox、Operaです.ブラウザのカーネルはマルチスレッドです.一つのブラウザは通常以下の常駐スレッドからなる.
  • レンダリングエンジンスレッド:名前の通り、このスレッドはページのレンダリングを担当しています.
  • JSエンジンスレッド:JSの解析と実行を担当する
  • タイミングフリップフロップスレッド:setTimeout、set Interval
  • などのタイミングイベントを処理する.
  • イベントトリガスレッド:DOMイベントを処理する
  • 非同期http要求スレッド:処理http要求
  • 注意したいのは、レンダリングスレッドとJSエンジンスレッドは同時に行われないことです.レンダリングスレッドはタスクを実行する時、JSエンジンスレッドが掛けられます.JSはDOMを操作できるので、レンダリング中にJSがDOMを処理すれば、ブラウザーはどうしたらいいか分かりません.
    JSエンジン
    ブラウザについては、通常、2つのエンジンについて話します.レンダリングエンジンとJSエンジンです.レンダリングエンジンはどのようにページをレンダリングしますか?Chrome/Safari/OperaはWebkitエンジンを使います.IEはTridentエンジンを使います.FireFoxはGeckoエンジンを使います.異なるエンジンが同一のスタイルに対して不一致を実現すると、よく非難されるブラウザスタイルの互換性が問題になります.ここでは具体的な議論はしません.
    JSエンジンはJS仮想マシンと言ってもいいです.JSコードの解析と実行を担当しています.通常は以下のステップを含みます.
  • ワード解析:ソースコードを意味のある単語に分解する
  • 文法分析:構文解析器を使って単語解析成語法樹
  • コード生成:マシンが動作するコードを生成する
  • コード実行
  • 異なるブラウザのJSエンジンもそれぞれ違っています.ChromeはV 8、FireFoxはSpider Monkey、SafariはJavaScript Core、IEはChokraを使っています.
    JSに戻るとシングルスレッドという言葉がありますが、本質的には、ブラウザはJSエンジンスレッドを開いて、JSを解析して実行しています.なぜエンジンが一つしかないですか?同時に二つのスレッドがDOMを操作すると、ブラウザはまた困惑しますか?
    JS運転機構
    こんなにたくさん話してから、やっとJSの運行過程について話します.
    同期実行
    まず、JS同期実行過程を見てみます.どうやってできますか?これは重要な概念である実行文脈に関連しています.私の訳文はJavaScriptのクローズドバッグを深く勉強して、この概念を詳しく説明しました.
    実行コンテキストはコード実行時の環境を記録しています.現在の運転状態にあり、実行コンテキストが働いています.実行文脈は何を記録していますか?語法環境、変数環境などがあります.簡単な例を挙げます.
    var x = 10;
    
    function foo(){
        var y=20;
        function bar(){
            var z=15; 
        }
        bar();
    }
    
    foo();
    
    コードの実行は、まずグローバルコンテキストに入ります.その後、foo()を実行すると、fooコンテキストに入ります.もちろん、グローバルコンテキストはまだあります.bar()を実行すると、またバーコンテキストに入ります.実行が完了したbar()は、fooコンテキストに戻る.foo()を実行した後、グローバルコンテキストに戻る.したがって、実行プロセスの実行文脈はコールスタックを形成し、先進的に後に出る.
    //   
                                                              3 bar Context
        =>                      =>   2 foo Context     =>     2 foo Context
            1 global Context         1 global Context         1 global Context
    
    //   
    3 bar Context
    2 foo Context     =>   2 foo Context     =>                        =>
    1 global Context       1 global Context         1 global Context
    
    JS実行中には、あるが、実行コンテキストだけが機能している.JSはシングルスレッドなので、一回に一つしかできません.
    以上のプロセスは同期して実行されます.
    非同期実行——イベントサイクル
    私達はJSの中でどれらの原生の非同期事件を持っていますか?
  • setTimeout
  • set Interval
  • 事件の傍受
  • Ajax要求
  • etc.
  • JS非同期の効果はブラウザの実行環境によるものである.実際、ブラウザはまたスレッドを開いて、これらのBOM事件を処理しています.例:
    function foo(){
        console.log(1);
    }
    
    function bar(){
        console.log(2);
    }
    
    foo();
    
    setTimeout(function cb(){
        console.log(3);
    });
    
    bar();
    
    前のセクションの分析に従って、まずグローバルコンテキストに入り、foo()に動作し、fooコンテキスト環境に入りました.console.log(1)を実行し、コンソール出力1.fooコンテキスト環境スタックは、setTimeoutに実行され、ブラウザに渡すタイミング処理スレッドです.bar()まで実行して、barコンテキスト環境に入りました.console.log(2)を実行し、コンソール出力2.fooコンテキスト環境の出スタック;ブラウザスレッドがsetTimeoutを実行した後、cb()に戻り、現在のジョブキューに戻る.実行スタックが空であると発見された場合、ブラウザのJSエンジンは一回のループを実行し、イベントキューのチームをJS実行スタックに最初にチームを出す.cb()を実行して、cbコンテキスト環境に入る.console.log(3)を実行し、コンソール出力3.イベントキューが空で、グローバルコンテキストがスタックから出ます.
    以上がJSエンジンのイベントサイクル機構であり、非同期を実現する仕組みである.主にブラウザスレッド、タスクキュー、JSエンジンに関連します.したがって、JSの非同期要求は、その環境ブラウザを使って処理し、結果を返すことができる.また、これらの非同期コードは、大域コンテキスト環境で実行されるので、これらのコールバック関数のthiswindowに向けられている理由も説明されている.
    後の話:自分の理解が正しいかどうか分かりません.不適当なところは指摘してください.
    参考資料:
  • JavaScript:同期、非同期、イベントサイクルを徹底的に理解する
  • はまだ疑惑を併発して並行しますか?
  • IMWebコミュニティブラウザプロセス?スレッド?馬鹿で分かりません.
  • Javascriptは、単一スレッドの深度解析
  • である.
  • JavaScript単一スレッドとブラウザイベントのループ概要
  • AlloyTeam【ステアリングJavascriptシリーズ】setTimeoutからのイベントサイクルモデル
  • ヒゲのお兄さんJavaScript非同期プログラミングの原理
  • 阮一峰JavaScript運行メカニズム詳細解:Event Loop
  • について説明します.
  • 【朴霊評注】JavaScript運行メカニズム詳細解:Event Loop
  • について説明します.
  • Philip Roberts:Help,I’m stuck in an event-loop.
  • Philip Roberts:What the heck is the event loop anyway?
  • jqueryにおけるAjaxの非同期