Как заставить программу ждать завершения HTTP-запроса в JavaScript?

Есть ли способ в JavaScript отправлять HTTP-запрос на HTTP-сервер и ждать ответа сервера? Я хочу, чтобы моя программа дождалась ответа сервера и не выполнила какую-либо другую команду после этого запроса. Если HTTP-сервер отключен, я хочу, чтобы HTTP-запрос повторялся после таймаута, пока сервер не ответит, а затем выполнение программы может продолжаться в обычном режиме.

Любые идеи?

Заранее спасибо, Thanasis

Ответ 1

Существует третий параметр для XmlHttpRequest:: open(), который указывает, что вы хотите, чтобы запрос был асинхронным (и таким образом обрабатывать ответ через обработчик onreadystate).

Итак, если вы хотите, чтобы он был синхронным (т.е. дождался ответа), просто укажите false для этого третьего аргумента. Вы также можете установить ограниченный ресурс тайм-аута для своего запроса в этом случае, поскольку он блокирует страницу до получения.

Здесь представлена ​​функция "все-в-одном" для синхронных и асинхронных операций:

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

который вы могли бы назвать следующим образом:

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

Ответ 2

Вы можете выполнить синхронный запрос. Пример jQuery:

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

Вы должны взглянуть на jQuery API AJAX. Я настоятельно рекомендую использовать фреймворк вроде jQuery для этого. Взаимодействовать с азаксом в кросс-браузере - настоящая боль!

Ответ 3

Вы можете использовать объект XMLHttpRequest для отправки вашего запроса. после отправки запроса вы можете иметь свойство readyState для идентификации состояния. readyState будет иметь следующие состояния.

  • uninitialized - еще не загрузился
  • Загрузка - загрузка
  • interactive - Загружен достаточно, и пользователь может взаимодействовать с ним.
  • complete - Полностью загружен

ex:

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

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

надеюсь, что это поможет

Ответ 4

Для этого вы можете запустить загрузчик в javascript, как только начнется загрузка страницы, а затем вы можете закрыть его, когда запрос завершится, или ваш дом готов.  Что я пытаюсь сказать, когда начинается загрузка страницы, запустите загрузчик. Затем страница может выполнять несколько синхронных запросов с помощью ajax до тех пор, пока вы не получите ответ, не закрывайте близкий загрузчик. После получения желаемого ответа в последнем вызове вы можете закрыть загрузчик.

Ответ 5

У меня такая же ситуация в игре, построенной с помощью Three.js и Google Closure. Мне нужно загрузить 2 ресурса, Три и Закрытие не позволяют мне делать эти синхронные.

Изначально я наивно писал следующее:

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).

Одним из решений может быть проверка обоих обратных вызовов, чтобы проверить, завершено ли последнее, и они продолжают инициировать цикл анимации.

Другое решение - возможно, более прямой ответ на то, что вы спрашиваете (как дождаться загрузки каждого из них до начала другого), - это вставить ответные вызовы следующим образом:

// 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
     ...

    });
  });
};