AJAX:Premiers pas
Un article de MDC.
> > Premiers pas
Cet article vous guide à travers les bases d'AJAX et vous donne deux
exemples clefs-en-main pour débuter.
[]
Qu'est-ce qu'AJAX ?
AJAX est un acronyme anglais signifiant Asynchronous JAvascript and XML
(Javascript et XML asynchrones). Pour simplifier, il s'agit d'employer l'objet
non standard XMLHttpRequest() pour communiquer avec des scripts situés sur le
serveur. L'objet permet d'échanger des informations sous différents formats
(dont XML, HTML ou texte), mais son principal attrait est sa nature
« asynchrone » : tout cela peut se faire sans recharger la page.
C'est ce qui permet de mettre à jour certaines parties d'une page sur base
d'évènements déclenchés par l'utilisateur.
Les deux fonctionnalités combinées sont les possibilités de :
- faire des requêtes vers le serveur sans avoir à recharger la page ;
- analyser et travailler avec des documents XML.
[]
Étape 1 - Lancement d'une requête HTTP
Pour faire une requête HTTP vers le serveur à l'aide de JavaScript, il faut
disposer d'une instance d'une classe fournissant cette fonctionnalité. Une telle
classe a d'abord été introduite dans Internet Explorer sous la forme d'un objet
ActiveX appelé XMLHTTP. Par la suite, Mozilla, Safari et d'autres
navigateurs ont suivi en implémentant une classe XMLHttpRequest qui
fournit les mêmes méthodes et propriétés que l'objet ActiveX original de
Microsoft.
Par conséquent, pour créer une instance (un objet) de la classe désirée
fonctionnant sur plusieurs navigateurs, vous pouvez utiliser :
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
http_request = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
http_request = new ActiveXObject("Microsoft.XMLHTTP");
}
(Pour illustrer le principe, le code ci-dessus est une version un peu
simplifiée de celui qui est utilisé pour créer une instance XMLHTTP. Pour un
exemple plus réaliste, voir la troisième étape de cet article.)
Certaines versions de certains navigateurs Mozilla ne fonctionneront pas
correctement si la réponse du serveur n'a pas un en-tête XML
mime-type. Pour vous en assurer, vous pouvez utiliser un appel de
fonction supplémentaire pour écraser l'en-tête envoyé par le serveur, juste au
cas où il ne s'agit pas de text/xml.
http_request = new XMLHttpRequest();
http_request.overrideMimeType('text/xml');
La chose suivante à faire est décider ce que vous ferez après avoir reçu la
réponse du serveur. À ce stade, vous devez juste communiquer à l'objet de
requête HTTP le nom de la fonction JavaScript qui effectuera le travail
d'analyse de la réponse. Pour cela, assignez à la propriété
onreadystatechange de l'objet le nom de la fonction JavaScript que
vous envisagez d'utiliser, comme ceci :
http_request.onreadystatechange = nomDeLaFonction;
Notez qu'il n'y a ni parenthèses après le nom de la fonction, ni paramètres
fournis, car vous ne faites qu'assigner une référence à la fonction sans
l'appeler effectivement. Par ailleurs, au lieu de donner un nom de fonction,
vous pouvez utiliser la technique JavaScript de définition de fonctions au vol
(ce qu'on appelle une fonction anonyme), et définir à cet endroit les actions à
effectuer sur la réponse, comme ceci :
http_request.onreadystatechange = function() {
// instructions de traitement de la réponse
};
Ensuite, après avoir déclaré ce qui se produit lorsque la réponse est reçue,
il s'agit de lancer effectivement la requête. Il faut pour cela appeler les
méthodes open() et send() de la classe de requête
HTTP, comme ceci :
http_request.open('GET', 'http://www.example.org/some.file', true);
http_request.send(null);
- Le premier paramètre de l'appel à
open() est la méthode de
requête HTTP – GET, POST, HEAD ou toute autre méthode que vous voulez utiliser
et est gérée par le serveur. Laissez le nom de la méthode en majuscules comme
spécifié par la norme HTTP ; autrement certains navigateurs (comme
Firefox) peuvent ne pas traiter la requête. Pour plus d'informations sur les
méthodes de requêtes HTTP possibles, vous pouvez consulter les spécifications du W3C
- Le second paramètre est l'URL de la page que vous demandez. Pour des
raisons de sécurité, il n'est pas possible d'appeler des pages se situant sur
un autre domaine. Veillez à utiliser le nom de domaine exact sur toutes vos
pages ou vous obtiendrez une erreur « permission refusée » à l'appel
d'
open(). Une erreur courante est de charger le site via
domaine.tld, mais d'essayer d'appeler des pages avec
www.domain.tld.
- Le troisième paramètre précise si la requête est asynchrone. Si mis à
TRUE, l'exécution de la fonction JavaScript se poursuivra en
attendant l'arrivée de la réponse du serveur. C'est le A d'AJAX.
Le paramètre de la méthode send() peut être n'importe quelle
donnée que vous voulez envoyer au serveur en cas d'utilisation de la méthode
POST. Les données doivent être sous la forme d'une chaîne de requête,
comme :
nom=valeur&autrenom=autrevaleur&ainsi=desuite
Notez que si vous voulez envoyer des données avec la méthode POST, vous
devrez changer le type MIME de la requête à l'aide de la ligne suivante :
http_request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
Autrement, le serveur ignorera les données envoyées.
[]
Étape 2 - Gestion de la réponse du serveur
Lors de l'envoi de la requête, vous avez désigné une fonction JavaScript pour
traiter la réponse.
http_request.onreadystatechange = nomDeLaFonction;
Voyons maintenant ce que cette fonction doit faire. Tout d'abord, elle doit
vérifier l'état de la requête. Si cet état a une valeur de 4, cela signifie que
la réponse du serveur a été reçue dans son intégralité et qu'elle peut
maintenant être traitée.
if (http_request.readyState == 4) {
// tout va bien, la réponse a été reçue
} else {
// pas encore prête
}
Voici la liste complète des valeurs de readyState :
- 0 (non initialisée)
- 1 (en cours de chargement)
- 2 (chargée)
- 3 (en cours d'interaction)
- 4 (terminée)
(Source)
La seconde vérification concerne le code d'état de la réponse HTTP du
serveur. Tous les codes possibles sont listés sur le site
du W3C. Dans notre cas, nous sommes seulement intéressés par la réponse
200 OK.
if (http_request.status == 200) {
// parfait !
} else {
// il y a eu un problème avec la requête,
// par exemple la réponse peut être un code 404 (Non trouvée)
// ou 500 (Erreur interne au serveur)
}
Après avoir vérifié l'état de la requête et le code d'état HTTP de la
réponse, vous pouvez traiter à votre guise les données envoyées par le serveur.
Il existe deux manières d'accéder à ces données :
http_request.responseText – renvoie la réponse du serveur
sous la forme d'une chaîne de texte
http_request.responseXML – renvoie la réponse sous la forme
d'un objet XMLDocument que vous pouvez parcourir à l'aide des
fonctions DOM de JavaScript
[]
Étape 3 - Un exemple simple
Rassemblons tous ces éléments dans un exemple : une requête HTTP simple.
Notre JavaScript demande un document HTML, test.html, qui contient
le texte « Je suis un test. », et nous affichons le contenu de ce
fichier test.html dans un message alert().
Effectuer une requête
Dans cet exemple :
- L'utilisateur clique sur le lien « Effectuer une requête » dans
le navigateur ;
- Ceci appelle la fonction
makeRequest() avec un paramètre – le
nom test.html d'un fichier HTML situé dans le même
répertoire ;
- la requête est faite et ensuite (
onreadystatechange)
l'exécution est passée à alertContents();
alertContents() vérifie si la réponse a été reçue et est
correcte, et affiche ensuite la contenu du fichier test.html dans
un message alert().
Vous pouvez tester
l'exemple ici et consulter le fichier
de test.
Note : La ligne
http_request.overrideMimeType('text/xml'); ci-dessus provoquera des
erreurs dans la console JavaScript de Firefox 1.5 ou supérieur (comme documenté
dans le bug
311724) si la page appelée par XMLHttpRequest n'est pas du XML valide (par
exemple s'il s'agit de texte simple). Ce comportement est en réalité le
comportement correct et cet article sera revu ultérieurement.
Note 2 : Si vous envoyez une requête vers un bout de code
dynamique qui renvoie du XML, plutôt que vers un fichier XML statique, vous
devez définir certains en-têtes de réponse pour que votre page fonctionne non
seulement avec Mozilla, mais aussi avec Internet Explorer. Si vous ne spécifiez
pas l'en-tête Content-Type: application/xml, IE produira une erreur
JavaScript « Objet attendu » après la ligne à laquelle vous tenterez
d'accéder à un élément XML. Si vous ne spécifiez pas l'en-tête
Cache-Control: no-cache, le navigateur mettra la réponse en cache
et n'effectuera plus jamais la requête ultérieurement, ce qui peut faire du
débogage un véritable défi.
Note 3 : Si la variable http_request est utilisée
globalement, des appels concurrents à makeRequest() peuvent
s'écraser l'un l'autre, provoquant un effet de race condition. On peut
s'en prémunir en rendant la variable http_request locale à la
fonction et en la passant en paramètre à la fonction
alertContent().
Note 4 : Pour procéder à l'enregistrement de la fonction de
callback onreadystatechange, aucun paramètre n'est permis. C'est
pourquoi le code suivant ne fonctionnera pas :
http_request.onreadystatechange = alertContents(http_request); // (ne fonctionne pas)
Pour enregistrer la fonction correctement, vous pouvez soit passer les
paramètres indirectement via la fonction anonyme, ou utiliser
http_request comme une variable globale. Voici quelques
exemples :
http_request.onreadystatechange = function() { alertContents(http_request); }; //1 (requêtes simultanées)
http_request.onreadystatechange = alertContents; //2 (variable globale)
La méthode 1 permet d'avoir plusieurs requêtes lancées simultanément, la
méthode 2 est utilisée si http_request est une variable globale.
Note 5 : Si erreur de communication se produit (par exemple le
serveur web qui cesse de répondre), une exception se déclenchera dans la méthode
onreadystatechange lors de l'accès à la variable
.status. Assurez-vous d'envelopper votre bloc
if...then dans un try...catch. (cf [1]).
function alertContents(http_request) {
try {
if (http_request.readyState == 4) {
if (http_request.status == 200) {
alert(http_request.responseText);
} else {
alert('Un problème est survenu au cours de la requête.');
}
}
}
catch( e ) {
alert("Une exception s'est produite : " + e.description);
}
}
[]
Étape 4 - Travailler avec des réponses XML
Dans l'exemple précédent, après la réception de la réponse à la requête HTTP,
nous avons utilisé la propriété responseText de l'objet de requête,
qui contient le contenu du fichier test.html. Essayons maintenant la
propriété responseXML.
Tout d'abord, créons un document XML valide qui sera l'objet de la requête.
Le document (test.xml) contient ce qui suit :
Je suis un test.
Dans le script, il est juste nécessaire de remplacer la ligne de requête
par :
...
onclick="makeRequest('test.xml')">
...
Ensuite, dans alertContents(), il faut remplacer la ligne
alert(http_request.responseText); par :
var xmldoc = http_request.responseXML;
var root_node = xmldoc.getElementsByTagName('root').item(0);
alert(root_node.firstChild.data);
De cette façon, nous avons pris l'objet XMLDocument donné par
responseXML et nous avons utilisé des méthodes DOM pour accéder à
certaines données contenues dans le document XML. Vous pouvez consulter le fichier
test.xml et le
script mis à jour.
Pour plus d'information sur les méthodes DOM, consultez les documents sur l'implémentation de DOM
dans Mozilla.