L'Objet XMLHttpRequest

Description basée sur la spécification du W3C avec un mode d'emploi.

Cet objet s'utilise en JavaScript pour échanger des données avec le serveur au format texte, XML ou JSON. Les fichiers XML sont automatiquement parsés par l'objet et accessibles par les méthodes du DOM. Les fichiers JSON sont parsés par la commande eval() de JavaScript.

Sommaire

Court historique

XMLHttpRequest, a été d'abord implémenté dans Internet Explorer depuis la version 4.0.
Ce concept s'appelait XMLHTTP dans les premiers temps, avant qu'Ajax ne devienne le nom le plus communément utilisé.
L'emploi de XMLHttpRequest en 2005 par Google, dans Gmail et GoogleMaps a contribué au succès de ce format.

Description

XHR est une classe qui est reconnue par tous les navigateurs actuels et par le langage de programmation fonctionnant coté client JavaScript.
Pour chaque requête au serveur, une nouvelle instance est créée par l'appel du constructeur.
La méthode open démarre la connexion, en mode lecture ou écriture, pour recevoir des données du serveur ou lui en envoyer. Ce sera traité sur le serveur par un langage coté serveur comme PHP, Java, etc...
La connexion passe par plusieurs états successifs qui sont assignés à l'attribut readyState de l'objet.
Quand l'état final est atteint, les données peuvent être récupérées dans un autre attribut. Elles sont du texte pur ou un document XML. Le format JSON est aussi reconnu.
Plus de détails sur l'utilisation de la classe dans le tutoriel Ajax.

Attributs

Le rôle des attributs de la classe est de se voir assigner l'état de la connexion, et les données reçues.

unsigned short readyState
Le code change successivement de valeur jusqu'à ce que le serveur soit prêt de, passant de 0 à 4 .
  • 0 Non initialisé
  • 1 Ouvert
  • 2 Envoyé
  • 3 Reçu
  • 4 Chargé
unsigned short status
200 est ok
404 si la page n'est pas trouvée.
DOMString statusText
Contient le libellé de l'état, correspondant au code d'état.
DOMString responseText
Contient les données chargées, au fur et à mesure, sous forme de chaine de caractères. Elle est complètement remplie quand l'état vaut 4.
document responseXml
Contient un fichier XML chargé, et les méthodes de DOM permettront d'en extraire les données. Elle est assignée seulement au moment ou l'état est 4, et vaut null avant.
EventListener onreadystatechange
Invoqué quand readyState est assigné.

Méthodes

Outre le constructeur, la classe a deux méthodes principales, open pour créer la session et désigner le fichier distant, et send pour tranférer les données sur le serveur.

abort()
Restaure l'objet et stoppe toute activité créée par l'objet.
getAllResponseHeaders()
Retourne tous les en-têtes dans une chaine, séparés par les codes CR et LF.
getResponseHeader(DOMString)
Retourne l'en-tête des données reçues après la dernière requête. Plusieurs en-têtes seraient séparées par une virgule, plus un espace.
open(mode, url, boolean [,login, password])
mode: type de requête, GET, POST, HEAD et autres méthodes de http.
url: le chemin du fichier.
boolean: true (vrai, asynchrone) / false (faux, synchrone).
optionellement, un login et un mot de passe comme argument supplémentaires.
send("string")
null ou vide avec la commande GET, sinon une chaine de caractères.
Lève une DOMException (INVALID_STATE_ERR) si le code readyState n'est pas 1.
setRequestHeader(DOMString, DOMString)
Les arguments sont le nom de l'en-tête et la valeur. Plusieurs valeurs peuvent être envoyées successivement.
Lève une DOMException (INVALID_STATE_ERR) si le code readyState ne vaut pas 1.

Comment utiliser XMLHttpRequest

La classe fait partie de ECMAScript (JavaScript) et est utilisée comme les autres classes du langage, mais elle a des constructeurs différents selon le navigateur.

Voilà le code complet pour ouvrir une session Ajax, en créant un nouvel objet XMLHttpRequest et en chargeant diverses données.
Le code peut être testé à partir des démos du site, notamment dans la section Scripts Ajax.

<html>
<head>
<script language="JavaScript">

 function submitForm()
 {
    var xhr=null;

   try
   {
     xhr = new XMLHttpRequest(); 
   } catch(e)
   { 
     try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); } 
     catch (e2)
    { 
       try { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } 
       catch (e) {}
    }
  }

  xhr.onreadystatechange = function()
   { 
     document.ajax.dyn.value="Wait server...";                
     if(xhr.readyState == 4)
     {
        if(xhr.status == 200)
        { 
             document.ajax.dyn.value="Received:" + xhr.responseText; 
        } 
       else 
        { 
              document.ajax.dyn.value="Error: returned status code " + 
                   xhr.status + " " + xhr.statusText; 
       } 
    } 
 }; 

 xhr.open("GET", "data.xml", true);                
 xhr.send(null); 
}

</script>
</head>
               
<body>
   <FORM method="POST" name="ajax" action="">                
    <INPUT type="submit" value="Submit" ONCLICK="submitForm()">
    <INPUT type="text" name="dyn" value=""> 
   </FORM>
</body>
</html> 

Le problème de mémoire cache

L'anté-mémoire fonctionne mal avec l'objet. Le fichier chargé par la méthode GET n'est pas toujours la dernière version mais le plus souvent une version conservée en mémoire cache.
Si le fichier n'est pas trop gros, cela peut se résoudre en ajouter un paramètre à la commande. Remplacer:

xhr.open("GET", "data.xml", true); 

par:

xhr.open("GET", "data.xml?nocache=" + Math.random(), true); 

Le problème des accents

L'encodage doit rester celui de la page HTML qui envoie les requêtes.
Sous Apache, cela nécessite éventuellement une petite reconfiguration: modifier la variable suivante dans httpd.conf:

AddDefaultCharset Off

Le format HTML

Puisque l'on peut charger des fichiers XML, peut-on aussi charger des fichiers HTML ou XHTML? En fait cela est prévu seulement pour la prochaine version de la spécification de XMLHttpRequest, de même que l'accès aux document sur d'autres sites Web que celui du serveur.
Il est prévu que dans ce cas, le type mime sera text/html tandis qu'il est text/xml pour les documents XML, dans l'en-tête de type de contenu.
En attendant, il existe une solution de remplacement avec un pseudo attribut responseHTML, qui est donnée sur ce site.

Demos

Une petite démo utilise la méthode HEAD pour lire les en-têtes d'une page Web.
Une autre démo montre les états successifs de readyState.
D'autres démos sont disponibles dans la section ressources ci-dessous.

Spécification et évolution du standard

Le W3C travaille sur une nouvelle spécification de l'objet nommée XMLHttpRequest Level 2. Parmi les nouvelles fonctionnalités offertes, citons les requêtes entre sites différents, les évènements progressifs, et la prise en charge de flux binaires en envoi et réception.

A coté de l'objet XMLHttpRequest lui-même, le W3C a établi une spécification pour les échanges entre sites nommée Access Control. Toutefois Microsoft a choisi de ne pas supporter ce protocole et propose à la place, dans Internet Explorer 8, le nouvel objet XDomainRequest. Celui-ci remplacera ou non XHR, cela dépend des fonctionnalités qu'il offrira dans la version finalisée.

Agent utilisateur

Ce mot revient souvent dans la spécification. Cela désigne n'importe quel outil qui accède à une page web ou un service: navigateur, robot de moteur de recherche, application cliente.

Ressources

Forum

Délai maximum pour réponse à HTMLrequest

21-07-2008 17:17:09

flashy38

Bonjour, Je constate que pour obtenir la réponse à une requête XMLHttpRequest, il existe un délai maximum, mais j'ignore quel est ce délai et surtout s'il existe une méthode pour contourner ce problème… Voici un exemple pour illustrer mon problème : Fichier test.html :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
<head>
<title>test</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="-1">
<meta name="robots" content="index,nofollow">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<script type="text/javascript">
function test()
{
    var xhr_object = null;

    if(window.XMLHttpRequest) // Firefox
       xhr_object = new XMLHttpRequest();
    else if(window.ActiveXObject) // Internet Explorer
       xhr_object = new ActiveXObject("Microsoft.XMLHTTP");
    else { // XMLHttpRequest non supporté par le navigateur
       alert("Votre navigateur ne supporte pas les objets XMLHTTPRequest...");
       return;
    }
    
    xhr_object.onreadystatechange = function() {
        if(xhr_object.readyState == 4) {
            var reponse= xhr_object.responseText;
            document.getElementById("reponse").innerHTML=reponse;
        }
    }
    
    xhr_object.open("GET","boucle.php",true);
    xhr_object.send();
    
}
</script>
</head>

<body>
<div id="reponse" style="border: 1px solid black; height:10px;"></div>
<input type="button" value="start" onclick="test()" />
</body>
</html>
Fichier boucle.php :
<?php
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");

@set_time_limit(0);

$nb_iter=60;  // nombre d'itérations
for ($i=0; $i<$nb_iter; $i++) {
    echo "boucle $i\n";
    sleep (1);
}
echo "Fin";
?>
Si je mets un nombre faible d'itérations (10 par exemple) dans le script boucle.php, là, pas de problème. Par contre, si je mets un nombre plus élevé d'itérations (120 par ex), je me retrouve avec ce message dans mon div "reponse" :
Network Error (tcp_error) A communication error occurred: "" The Web Server may be down, too busy, or experiencing other problems preventing it from responding to requests. You may wish to try again at a later time.
Vous aurez bien compris, vu l'utilité d'un tel script, il ne s'agit là que d'un exemple !!! En réalité, je souhaite lancer, via ajax, l'upload en FTP de fichiers de taille importante (100 Mo et plus) pour récupérer et afficher le résultat (réussite ou echec avec endroit où c'est produite l'erreur). Merci d'avance de votre aide...
23-07-2008 14:52:07

webmaster

Bonjour, L'utilisation de la fonction setTimeout de JavaScript pourrait peut-être résoudre le problème. La fonction setTimeOut permet en effet d'exécuter une fonction à intervalle donné et donc de limiter le temps de connexion ou le volume dans un temps donné selon la façon dont on l'utilise.
function x()
{
}
var y=setTimeout('x();',1000);
Le second paramètre est le délai en microsecondes avant l'appel de la fonction. A mettre dans une boucle... Encore le temps de connexion dépend-t-il aussi du serveur qui peut en limiter la durée. Dans ce cas il n'y a pas de solution sauf diviser la tâche en plusieurs tâches moins longues...
© 2006-2013 Xul.fr