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.
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 .
|
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
- Spécification XMLHttpRequest, document de travail. La traduction française est faite par Xul.fr
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
- JavaScript. Syntaxe et études de cas utilisant Ajax.
- Tutoriel Ajax. Création de pages web dynamiques en utilisant XMLHttpRequest et JavaScript.
- Demos Ajax. Démonstrations utilisant XMLHttpRequest.
Délai maximum pour réponse à HTMLrequest
flashy38
<!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...
webmaster
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...