web-dev-qa-db-fra.com

Comment forcer un programme à attendre qu'une requête HTTP soit terminée en JavaScript?

Existe-t-il un moyen en JavaScript d'envoyer une requête HTTP à un serveur HTTP et d'attendre que le serveur réponde avec une réponse? Je veux que mon programme attende que le serveur réponde et n'exécute aucune autre commande postérieure à cette demande. Si le serveur HTTP est en panne, je souhaite que la demande HTTP soit répétée après un délai expirant jusqu'à ce que le serveur réponde, puis l'exécution du programme peut continuer normalement.

Des idées?

Merci d'avance, Thanasis

14
Thanasis Petsas

Il existe un 3ème paramètre pour open() de XmlHttpRequest, qui vise à indiquer que vous voulez que la demande soit asynchrone (et donc gérer la réponse via un gestionnaire onreadystatechange.). 

Donc si vous voulez qu'elle soit synchrone (attendez la réponse), spécifiez simplement false pour ce 3ème argument . Vous pouvez également définir une propriété timeout limitée pour votre requête dans ce cas, car cela bloquerait la page jusqu'à la réception.

Voici un exemple de fonction tout-en-un pour la synchronisation et l'async:

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;
}

que vous pourriez appeler de cette façon:

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
26
Javarome

Vous pouvez effectuer une requête synchrone. Exemple jQuery:

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

Vous devriez jeter un oeil à l'API AJAX de jQuery. Je recommande fortement d'utiliser un framework comme jQuery pour ce genre de choses. Faire manuellement du ajax sur plusieurs navigateurs est une vraie douleur!

9
jwueller

Vous pouvez utiliser l'objet XMLHttpRequest pour envoyer votre demande. Une fois la demande envoyée, vous pouvez vérifier la propriété readyState pour identifier l'état actuel. readyState aura différents états suivants.

  • Non initialisé - Le chargement n'a pas encore commencé 
  • Chargement en cours
  • Interactif - A suffisamment chargé et l'utilisateur peut interagir avec lui
  • Complet - Complètement chargé

par exemple: 

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

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

espérons que cela aidera

5
Ashif Nataliya

J'ai une situation similaire dans un jeu construit avec Three.js et Google Closure. Je dois charger 2 ressources, Three et Closure ne me permettent pas de les rendre synchrones.

Au départ, j’ai écrit naïvement ce qui suit:

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
  ...
};

La boucle qui attend que les rappels soient terminés ne se termine jamais, du point de vue de la boucle loaded, jamais incrémentée. Le problème est que les rappels ne sont pas déclenchés avant le retour de main (du moins sur Chrome de toute façon).

Une solution pourrait consister à faire vérifier les deux callbacks pour voir s’il s’agit du dernier à terminer, puis à lancer la boucle d’animation.

Une autre solution - peut-être une réponse plus directe à ce que vous demandez (comment attendre chaque chargement avant d’en lancer un autre) - consisterait à imbriquer les rappels comme suit:

// 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
Argenti Apparatus

Pour cela, vous pouvez démarrer le chargeur en javascript dès que le chargement de la page commence, puis vous pouvez le fermer lorsque la demande est terminée ou que votre dom est prêt . Ce que j'essaie de dire, au début du chargement de la page, démarrez un chargeur. Ensuite, page peut faire plusieurs demandes synchrones en utilisant ajax, jusqu'à ce que et à moins que vous n'ayez pas reçu de réponse, ne fermez pas le chargeur fermé . 

0
Nik