JavaScriptはバックグラウンドでAJAX応答をどのように処理しますか?


139

JavaScriptはシングルスレッドで実行されるため、AJAXリクエストが行われた後、バックグラウンドで実際に何が起こりますか?これについてより深い洞察を得たいのですが、誰かが光を当てることはできますか?


6
かなり良い説明がここにあります:stackoverflow.com/questions/2914161/ajax-multi-threaded
Jonathan M

3
JavaScriptコードはシングルスレッド(Webワーカーを除く)ですが、JavaScriptエンジンを実行しているブラウザーではありません...
Juan Mendes

@JuanMendesイベントキューが別のスレッドで実行されている間、JavaScriptは1つのスレッドで実行されますか?
Shaun Luttin、2015

1
@ShaunLuttinいいえ、JavaScriptを開始するのはイベントキューです
ファンメンデス

回答:


213

カバーの下に、JavaScriptにはイベントキューがあります。実行のJavaScriptスレッドが終了するたびに、処理するキューに別のイベントがあるかどうかを確認します。存在する場合は、キューからそれを引き出し、そのイベントをトリガーします(たとえば、マウスクリックなど)。

ajax呼び出しの下にあるネイティブコードネットワーキングは、ajax応答がいつ完了したかを認識し、イベントがjavascriptイベントキューに追加されます。ajax呼び出しがいつ行われるかをネイティブコードがどのように認識するかは、実装によって異なります。スレッドで実装することも、それ自体がイベントドリブンにすることもできます(これは重要ではありません)。実装のポイントは、ajax応答が完了すると、一部のネイティブコードがそれが完了したことを認識し、イベントをJSキューに入れることです。

その時点でJavaScriptが実行されていない場合、イベントはすぐにトリガーされ、ajax応答ハンドラーが実行されます。その時点で何かが実行されている場合、実行の現在のJavaScriptスレッドが終了すると、イベントが処理されます。JavaScriptエンジンによるポーリングは必要ありません。JavaScriptの一部が実行を終了すると、JSエンジンはイベントキューをチェックして、実行する必要があるものがあるかどうかを確認します。その場合、次のイベントをキューからポップして実行します(そのイベントに登録されている1つ以上のコールバック関数を呼び出します)。イベントキューに何もない場合、JSインタープリターには、外部エージェントが何かをイベントキューに入れて再びウェイクアップするまで、空き時間(ガベージコレクションまたはアイドル)があります。

すべての外部イベントはイベントキューを通過し、JavaScriptが実際に何かを実行している間はイベントがトリガーされないため、シングルスレッドのままです。

詳細は次のとおりです。


それをありがとう。私はこれが事実であると疑ったが、確かに知っておくと良い。私はforループを持っており、たくさんの「ajax」リクエストを送信します。私のハンドラーでは(要求ごとに-任意の順序で返されます)、時間がかかる可能性があるコードを実行します。これは間違いなく機能するはずです。
iPadDeveloper2011

4
@telandor-イベントはFIFOの順序で実行されます(エッジケースの例外が発生する可能性がありますが、意図はFIFOです)。一部のイベントは少し異なる方法で処理されます。たとえば、mousemoveイベントはキューに蓄積されません(おそらく、キューがオーバーフローする可能性が高いためです)。マウスが移動し、mousemoveイベントがすでにキューにあり、キューに他の新しいイベントがない場合、新しいイベントが追加されるのではなく、最新の位置で更新されます。インターバルタイマーイベントも、キューに蓄積されないように特別に処理されると思います。
jfriend00 2013

2
@telandor-何をさらに説明する必要がありますか?FIFOです。私は私の回答にいくつかの参照記事を追加しました。私が知っているFIFOへの唯一の実行は、即座にトリガーされるイベントです。.focus()アイテムを呼び出すと、フォーカスのあるアイテムに対する「ぼかし」イベントなど、他の2つのイベントがトリガーされます。このぼかしイベントは同期的に発生し、イベントキューを通過しないため、イベントキューにある他のイベントの直前に発生します。実際には、これが実用的な問題であるとは思いもしませんでした。
jfriend00

2
@telandor-ブラウザドキュメントごとに複数のキューはありません。キューが1つあり、すべてがシリアルにFIFOイン/アウトになります。したがって、タイムアウトとajax応答、マウスイベントとキーボードイベントはすべて同じキューに入ります。最初にキューに入れられた方が最初に実行されます。
jfriend00

1
@CleanCrispCode-Thx。私はそれを私の回答への有用な参照として追加しました。
jfriend00

16

JavaScriptでのイベント処理に関する非常に完全なドキュメントをここで見つけることができます。
これは、OperaブラウザーでのJavaScriptの実装に取り​​組んでいる人によって書かれています。

より正確には、「イベントフロー」、「イベントキューイング」、および「非ユーザーイベント」というタイトルを見てください。次のことがわかります。

  1. JavaScriptは、ブラウザのタブまたはウィンドウごとに1つのスレッドで実行されます。
  2. イベントはキューに入れられ、順次実行されます。
  3. XMLHttpRequestは実装によって実行され、コールバックはイベントキューを使用して実行されます。

注:元のリンクだったリンクが、今死んでいます。


1

回答に記載されているajax実装について少し詳しく説明します。

(通常の)Javascriptの実行ではあるがない、マルチスレッド-上記の回答でも述べたように- しかし、の本当の取り扱いAJAX responses(リクエストの処理だけでなく、など)がありません Javascriptを、そしてそれは-通常- であるマルチスレッド。(前述のXMLHttpRequestのクロムソース実装を参照してください)

説明します。次のコードを見てみましょう。

var xhr = new XMLHttpRequest();

var t = Date.now;
xhr.open( "GET", "https://swx.cdn.skype.com/shared/v/1.2.15/SkypeBootstrap.min.js?v="+t(), true );

xhr.onload = function( e ) {
		console.log(t() + ': step 3');
    
    alert(this.response.substr(0,20));
};
console.log(t() + ': step 1');
xhr.send();
console.log(t() + ': step 2');

after an AJAX request is made(-ステップ1の後)、jsコードの実行が続行している間(ステップ2以降)、ブラウザーは次の実際の作業を開始します。1. tcpリクエストのフォーマット2.ソケットのオープン3.ヘッダーの送信4.ハンドシェイク5.送信本体6.応答の待機7.ヘッダーの読み取り8.本体の読み取りなどこの実装はすべて、通常、jsコードの実行と並行して別のスレッドで実行されます。例として、言及されているchromiumの実装は、Threadable Loader go digg-intoを使用しています(ページのロードのネットワークタブを見ると、いくつかの同時リクエストが表示されます)。

結論として、私は-少なくとも-ほとんどのI / O操作を同時に/非同期に行うことができます(そして、たとえばawaitを使用しこれを利用できます)。ただし、これらの操作(発行、jsコールバックの実行)とのすべての対話はすべて同期です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.