Как заставить программу ждать до завершения HTTP-запроса в JavaScript? - PullRequest
16 голосов
/ 21 сентября 2010

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

Есть идеи?

Спасибо заранее, Thanasis

Ответы [ 5 ]

27 голосов
/ 30 декабря 2012

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

Так что, если вы хотите, чтобы он был синхронным (т. Е. Дождался ответа), просто укажите 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
8 голосов
/ 21 сентября 2010

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

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

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

5 голосов
/ 21 сентября 2010

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

  • Uninitialized - загрузка еще не началась
  • Загрузка - Идет загрузка
  • Интерактив - достаточно загружен, и пользователь может взаимодействовать с ним
  • Complete - полностью загружен

например:

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

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

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

0 голосов
/ 30 декабря 2011

У меня похожая ситуация в игре, созданной с помощью 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
     ...

    });
  });
};
0 голосов
/ 21 сентября 2010

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

...