この記事は編集レビューを必要としています。ぜひご協力ください。
この翻訳は不完全です。英語から この記事を翻訳 してください。
JavaScriptは、"event loop"に基づく同時並行性モデルを持ちます。このモデルはC言語やJavaのような他の言語のモデルとかなり異なっています。
ランタイムの概要
次のセクションでは、理論モデルを説明します。現代のJavaScriptエンジンが頻繁に記載されたセマンティクスを実装し、最適化します。
視覚表示
スタック
framesのスタックからの関数呼び出し
function f(b){ var a = 12; return a+b+35; } function g(x){ var m = 4; return f(m*x); } g(21);
g
を呼び出すとき、最初のフレームは、g
引数とローカル変数を含んで生成されます。g
がf
を呼び出すとき、2番目のフレームが、f
引数とローカル変数を含んで最初のフレームの先頭に生成され、押し上げられます。f
が返るとき、先頭のフレーム要素はスタックからポップされます。(唯一g
コールフレームを残します)。g
が返るとき、スタックは空になります。
ヒープ
オブジェクトはヒープに割り当てられています。ヒープは、メモリの大規模で大部分は構造化されていない領域を意味する名前です。
キュー
JavaScriptランタイムはメッセージキューを含んでいます。メッセージキューは、処理されるメッセージのリストです。各メッセージに関数を関連付けられています。スタックが空のとき、メッセージがキューから取り出され、処理されます。その処理は、関連する関数の呼び出し(と最初のスタックフレームの作成)で構成されています。スタックが再度空になると、メッセージ処理は終了します。
イベントループ
event loop
は、通常似ている実装方法のための名前を取得します。:
while(queue.waitForMessage()){ queue.processNextMessage(); }
queue.waitForMessage
は、どれもが現在存在しない場合は到着するメッセージの同期を待ちます。
"Run-to-completion"
その他のメッセージが処理される前に、各メッセージは完全に処理されています。 関数が実行されるたびに、それが横取りすることはできず、他のコードが実行される前に、完全に実行されます(および関数が操作するデータを変更することができる)という事実を含め、プログラムについて推論するときにいくつかの素晴らしい特性を提供しています。例えば、これはCとは異なります。というのは、関数はスレッドで実行されている場合、それは別のスレッドでいくつかの他のコードを実行するには、任意の時点で停止することができます。
このモデルの欠点は、メッセージが完了するまでに時間がかかりすぎる場合は、Webアプリケーションはクリックやスクロールのようなユーザインタラクションを処理することができないことです。ブラウザは"スクリプトは実行に非常に時間がかかる"ダイアログを用いてこれを軽減します。追従するお勧めは、メッセージを短い処理にし、可能な場合には、いくつかのメッセージに一つのメッセージを切り縮めることです。
メッセージの追加
Webブラウザでは、メッセージは、イベントが発生し、それに接続されているイベントリスナーがある任意の時間に追加されます。イベントリスナーがない場合、イベントは失われます。だから、他のイベントと同様に、クリックイベントハンドラを持つ要素をクリックすると、メッセージが追加されます。
setTimeout
を呼び出すと、2番目の引数として渡された時間が経過した後、メッセージがキューに追加されます。キューに他のメッセージがない場合、メッセージはすぐに処理されます。しかしながら、メッセージがある場合、setTimeout
メッセージは他のメッセージを処理するために待機する必要があります。そのため第二引数は、保証時間ではなく、最小の時間を示しています。
一緒に通信するいくつかのランタイム
ウェブワーカーやクロスオリジンのiframeは、独自のスタック、ヒープ、およびメッセージキューがあります。二つの異なるランタイムのみpostMessage
メソッドによって送信メッセージを介して通信することができます。他のランタイムがmessage
イベントをリッスンする場合、このメソッドは他のランタイムにメッセージを追加します。
ブロッキング不可
イベントループモデルの非常に興味深い属性は、他の言語の多くとは異なり、JavaScriptは決してブロックしないことです。I/Oの取り扱いは、通常、イベントとコールバックを介して行われます。だから、アプリケーションが返すためのIndexedDBクエリまたは返すためのXHRリクエストを待っているときに、まだユーザ入力のような他のものを処理することができます。
alert
か同期XHRのようにレガシー例外が存在します。しかし、それらを避けることをお勧めのように考えられています。exceptions to the exception do existに気をつけてください。(しかし、むしろ他の何よりも、通常の実装のバグがあります。)