web-dev-qa-db-ja.com

JavaScriptでHTTPリクエストが完了するまでプログラムを強制的に待機させる方法は?

JavaScriptでHTTPリクエストをHTTPサーバーに送信し、サーバーが応答するまで待機する方法はありますか?私のプログラムは、サーバーが応答するまで待機し、この要求の後にある他のコマンドを実行しないようにします。 HTTPサーバーがダウンしている場合、タイムアウト後にサーバーが応答するまでHTTPリクエストを繰り返して、プログラムの実行を正常に続行できるようにします。

何か案は?

Thanasisよろしくお願いします

21
Thanasis Petsas

XmlHttpRequestopen()には3番目のパラメーターがあり、非同期でリクエストを送信することを示します(したがって、onreadystatechangeハンドラーを介して応答を処理します)。

したがって、同期させる(つまり、応答を待つ)場合は、この3番目の引数にfalseを指定します。この場合、リクエストまでに制限されたtimeoutプロパティを設定することもできます。これは、受信までページをブロックするためです。

同期と非同期の両方のオールインワンサンプル関数を次に示します。

function httpRequest(address, reqType, asyncProc) {
  var req = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
  if (asyncProc) { 
    req.onreadystatechange = function() { 
      if (this.readyState == 4) {
        asyncProc(this);
      } 
    };
  } else { 
    req.timeout = 4000;  // Reduce default 2mn-like timeout to 4 s if synchronous
  }
  req.open(reqType, address, !(!asyncProc));
  req.send();
  return req;
}

あなたはこのように呼ぶことができます:

var req = httpRequest("http://example.com/aPageToTestForExistence.html", "HEAD");  // In this example you don't want to GET the full page contents
alert(req.status == 200 ? "found!" : "failed");  // We didn't provided an async proc so this will be executed after request completion only
29
Javarome

同期リクエストを実行できます。 jQueryの例:

$(function() {
    $.ajax({
       async: false,
       // other parameters
    });
});

JQueryの AJAX API をご覧ください。このためには、jQueryのようなフレームワークを使用することを強くお勧めします。手動でクロスブラウザーのajaxを実行するのは本当に大変です。

8
jwueller

XMLHttpRequestオブジェクトを使用してリクエストを送信できます。リクエストが送信されたら、readyStateプロパティをチェックして現在の状態を特定できます。 readyStateには以下の異なる状態があります。

  • 未初期化-まだロードを開始していません
  • 読み込み中-読み込み中です
  • インタラクティブ-十分にロードされ、ユーザーはインタラクティブに操作できます
  • 完了-完全に読み込まれました

例えば:

xmlhttp.open("GET","somepage.xml",true);
xmlhttp.onreadystatechange = checkData;
xmlhttp.send(null);

function checkData()
{
    alert(xmlhttp.readyState);
}

これが役に立てば幸い

5
Ashif Nataliya

Three.jsとGoogle Closureで構築されたゲームでも同様の状況があります。 2つのリソースをロードする必要があります。ThreeとClosureでは、これらを同期させることができません。

最初、私は単純に次のように書きました:

main() {

  ...
  var loaded=0;
  ...

  // Load Three geometry
  var loader = new THREE.JSONLoader();
  loader.load("x/data.three.json", function(geometry) {
    ...
    loaded++;
    });

   // Load my engine data
  goog.net.XhrIo.send("x/data.engine.json", function(e) {
    var obj = e.target.getResponseJson();
    ...
    loaded++;
    });

  // Wait for callbacks to complete
  while(loaded<2) {}

  // Initiate an animation loop
  ...
};

コールバックの完了を待機するループは決して終了しません。ループの観点からは、loadedはインクリメントされません。問題は、コールバックがmainが返されるまで発生しないことです(少なくともChromeとにかく))。

1つの解決策は、両方のコールバックをチェックして、それが最後に完了するかどうかを確認し、アニメーションループを開始することです。

別の解決策-おそらくあなたが求めていることに対するより直接的な答え(別のロードを開始する前に各ロードを待機する方法)-は、次のようにコールバックをネストすることです:

// Load Three geometry
var loader = new THREE.JSONLoader();
loader.load("x/data.three.json", function(geometry) {
  ...

   // Load my engine data
   goog.net.XhrIo.send("x/data.engine.json", function(e) {
     var obj = e.target.getResponseJson();
     ...

     // Initiate an animation loop
     ...

    });
  });
};
0

このため、ページのロードが開始されるとすぐにJavaScriptでローダーを開始し、リクエストが終了するか、DOMの準備ができたときにローダーを閉じることができます。私が言おうとしていることは、ページのロードが始まると、ローダーを開始することです。その後、ページはajaxを使用して複数の同期リクエストを実行できます。応答が得られない限り、クローズローダーを閉じないでください。最終呼び出しで必要な応答を受け取った後、ローダーを閉じることができます。

0
Nik