Tutorial sur les requêtes serveur en JavaScript
Avant d'entrer dans le vif du sujet, je tiens à remercier tous les habitués du forum de ToutJavaScript.com et notamment Aurélien pour son explication limpide sur les fonctions à retardement (j'espère les avoir bien utilisées) et poof65 pour sa collaboration lors de la création d'une classe d'abstraction des objets XMLHTTPRequest.
[1]
Opera est actuellement en train d'évoluer et devrait bientôt gérer
complètement ces objets. Au moment où j'écris ces lignes, les exemples
des sections 1. et 2. fonctionnent normalement sous Opera 8 beta.
L'exemple de la section 3. fonctionne mais le résultat arrive deux
fois. Celui de la section 4. ne fonctionne qu'avec la méthode get. Et le dernier, celui de la section 5. fait carrément planter l'application.
Accès rapide aux sections
1. Présentation
Comme leur nom ne l'indique pas, les objets XMLHTTPRequest permettent de récupérer toutes sortes de données, et pas seulement des fichiers XML. Pour effectuer une requête, il faut tout d'abord déclarer une certaine variable. Ce qui se fait de manière différente avec IE et Firefox. Sous IE, on utilise un objet ActiveX et sous Firefox, on dispose d'un type ad hoc.
Ensuite, on envoie la requête et enfin, on attend la réponse. Ci-après,
vous pouvez voir un exemple très basique faisant une requête sur la
présente page (location.href). Une fois la réponse obtenue, une boîte d'alerte s'affiche.
Comment ça marche ?
- ligne 4 : on crée une instance de l'objet XMLHTTPRequest sous Firefox ;
- ligne 6 : on crée une instance de l'objet XMLHTTPRequest sous IE ;
- ligne 12 : on spécifie la méthode de transmission des données, l'URL et le mode de transmission de la requête ;
- ligne 13 : on exécute la requête proprement dite ;
- ligne 14 : on affiche une boîte d'alerte dès que la requête est terminée.
2. À quoi cela peut-il servir ?
Dans l'exemple précédent, la requête se contente de demander un
certain fichier sans s'occuper du résultat. Mais en fait, lorsque la
requête se termine, on reçoit (et heureusement) des informations du
serveur. Ces informations sont contenues dans la variable xhr_object.responseText ou xhr_object.responseXML,
selon que le résultat est au format texte (il est possible de mettre
n'importe quoi dedans, tout est question d'interprétation ultérieure de
ce résultat) ou XML. Remplaçons simplement l'alerte de l'exemple précédent par alert(xhr_object.responseText) (cf. ligne 14) et voyons le résultat :Note : La section 5 présente un exemple concret d'utilisation.
3. Synchrone Vs. Asynchrone
Dans les exemples que nous avons vus jusqu'à maintenant, c'est le mode synchrone
qui était utilisé. Cela signifie que tant que le résultat de la requête
ne nous est pas parvenu, le script est en pause et le navigateur
bloqué. Avec un bon débit et/ou peu de données à transmettre, on
pourrait s'en contenter mais cela peut vite s'avérer gênant pour
l'utilisateur qui voit son navigateur figé. Ce mode de transmission est
donc à proscrire. Heureusement, il existe le mode asynchrone. Dans ce mode, après avoir envoyé la requête via send,
le script poursuit son exécution, sans bloquer le navigateur.
Évidemment, dans ce mode, il faut prévoir quelque chose pour nous
prévenir quand la requête a abouti. C'est le rôle de la fonction onreadystatechange (en fait, onreadystatechange
est une propriété et non une fonction, mais comme on lui affecte un
pointeur vers une fonction nous pouvons nous permettre cet abus de
langage). Prenons comme nouvel exemple une requête sur un simple
fichier texte :> Voir le contenu de foo.txt
Comment ça marche ?
C'est le troisième argument de la fonction open (cf. ligne 12) qui spécifie que le mode doit être asynchrone.L'objet xhr_object possède une propriété readyState (cf. ligne 15) qui prend successivement 5 valeurs récapitulées dans le tableau suivant :
| Valeur | Description |
|---|---|
| 0 (uninitialized) | non initialisé |
| 1 (loading) | début du transfert des données |
| 2 (loaded) | données transférées |
| 3 (interactive) | les données reçues sont accssibles en partie |
| 4 (complete) | les données sont complètement accessibles |
> Voir toutes les valeurs
4. Transmettre des données
Réaliser une requête et recevoir un résultat, c'est bien. Mais
réaliser une requête en transmettant des données c'est mieux. Les
données sont transmises de la même façon que lors de la soumission d'un
formulaire, c'est-à-dire via l'une des deux méthodes get ou post.
Évidemment, si on transmet des données, il faut que la requête porte
sur un fichier capable de les interpréter correctement. Dans l'exemple
suivant, nous allons envoyer deux chaînes de caractères au fichier strings2.php et celui-ci va nous les retourner « renversées ».> Voir le contenu de strings2.php
Comment ça marche ?
Tout commence en JS. Si la méthode sélectionnée est get, les données à transmettre sont concaténées à l'URL (cf. lignes 21-24) et si la méthode est post, elles sont envoyées via la fonction send (cf. ligne 42). Dans ce dernier cas, on doit aussi préciser l'encodage en spécifiant l'en-tête adéquat avec setRequestHeader (cf. ligne 40).Ensuite, côté PHP, les données sont reçues, quelle que soit la méthode de transmission et les chaînes sont renversées grâce à strrev (cf. lignes 3-12). Les données reçues via la méthode POST sont décodées grâce à utf8_decode sinon les caractères accentués sont mal interprétés. La chaîne affichée par le code PHP (et retournée, donc) est de la forme Données reçues en XXX:STRING1:STRING2: où XXX vaut soit GET soit POST et où STRING1 et STRING2 sont les chaînes renversées. On précise aussi, grâce à la fonction header le type des données qui vont être transférées depuis le serveur (ici, du texte utilisant le jeu de caractères iso-8859-1) (cf. ligne 1).
Enfin, côté JS, il ne reste plus qu'à séparer les données, avec split et à mettre les chaînes dans les champs correspondants (cf. lignes 30-34).
5. Exemple concret d'utilisation
Comme nous l'avons vu dans les exemples précédents, nous disposons
d'une grande liberté d'action avec cet outil. On peut simplement
afficher le résultat de la requête dans une boîte d'alerte. On peut
également l'afficher dans un div (ou tout autre élément HTML). Mais on peut tout aussi bien, si la chaîne récupérée représente du code JS, exécuter ce code grâce à eval.Voici un exemple dans lequel une liste déroulante est peuplée en fonction du choix réalisé dans une première liste. Le code JS qui permet de remplir la seconde liste est généré côté serveur, suite à une requête MySQL et simplement évalué côté client.
> Voir le contenu de species.php
> Voir la table « Animals »
Comment ça marche ?
Dans cet exemple, seules les notions couvertes dans les sections 1.
à 4. sont utilisées, ainsi que quelques notions élémentaires de JS et de PHP. Vous devriez donc logiquement pouvoir comprendre le code par vous-même. Si, si, j'en suis sûr.
6. Propriétés et méthodes
Cette section n'est pas exhaustive. Elle présente les propriétés et
méthodes les plus utiles, même s'il est vrai que cette notion est assez
subjective. Pour une liste complète, je vous invite à consulter la MSDN
dont un lien est donné en section 7.
Propriétés
- onreadystatechange : Spécifie la fonction à appeler lorsque la propriété readyState varie. lecture/écriture. (Cf. section 3 pour les valeurs)
- readyState : Représente l'état d'avancement de la requête. lecture seule.
- responseText : Chaîne de caractères contenant la réponse à la requête. lecture seule.
- responseXML : Objet XML contenant la réponse à la requête. lecture seule.
- status : Représente le code HTTP retourné par la requête. lecture seule. (Cf. section 3 pour les valeurs)
Méthodes
- abort() : Annule la requête courante.
- getAllResponseHeaders() : Retourne les noms et les valeurs de tous les en-têtes HTTP sous forme d'une chaîne.
- getResponseHeader(headerName) : Récupère la valeur d'un certain en-tête HTTP (headerName) sous forme d'une chaîne.
- open(method, url[, asynchrone[, user[, password]]]) : Initialise une requête en spécifiant la méthode (method), l'URL (url), si le mode est asynchrone (asyncFlag vaut true ou false) et en indiquant d'éventuelles informations d'identification (user et password).
- send(data) : Envoie la requête HTTP au serveur en transmettant éventuellement des données (data doit alors être différent de null) sous forme d'une « postable string » (je suis preneur pour une traduction) ou sous forme d'un objet DOM.
- setTimeouts(timeout) : Spécifie la durée maximale (timeout) accordée à une requête pour quelle s'effectue complètement.
- setRequestHeader(headerName, headerValue) : Spécifie un en-tête HTTP (headerName et headerValue) à envoyer avec la requête.
7. Quelques liens
Des exemples d'utilisation :
- Une petite page de démonstration (qui perd un peu de son sens face à ce tutorial) :
http://robloche.free.fr/javascript/js_request/test.html - Et
voici le concept poussé un plus loin, avec un jeu de morpion acceptant
un grand nombre de participants (enfin, deux par jeu, quand même). J'ai
écrit dans ce but une classe d'abstraction qui permet de manipuler ces
objets sans se soucier du navigateur. Cette classe constitue une
surcouche aux objets XMLHTTPRequest et permet de réaliser certaines opérations complexes en ne fournissant que quelques paramètres :
http://robloche.free.fr/javascript/morpion/morpion.php - Une
nouvelle mouture de Google, actuellement en version beta, propose des
suggestions pour votre recherche, en utilisant cette technique :
http://www.google.com/webhp?complete=1&hl=en - Et bien sûr, tout ceux qui ont un compte Gmail savent à quel point il est fait un usage intensif de cette technologie :
http://gmail.google.com - Depuis quelques mois, on voit régulièrement fleurir de nouvelles utilisations de ces requêtes JS sur le net. Et ça ne risque pas de s'arrêter, tant il est vrai que ça simplifie la vie des visiteurs. Observez bien les sites que vous fréquentez et essayez de deviner s'ils utilisent cette technique.
D'autres liens utiles :
- La page de la MSDN détaillant toutes les méthodes et propriétés des objets XMLHTTPRequest :
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/xmlsdk/html/xmobjpmeserverxmlhttp.asp - Un article intitulé Dynamic HTML and XML: The XMLHttpRequest Object sur developer.apple.com :
http://developer.apple.com/internet/webcontent/xmlhttpreq.html - Une page traitant également du sujet sur www.mozilla.org :
http://www.mozilla.org/xmlextras/ - Un article intitulé Using the XML HTTP Request object introduisant ces mêmes objets :
http://jibbering.com/2002/4/httprequest.html - Comme
vous l'avez remarqué, tous les codes visibles sur cette page présentent
une coloration syntaxique bien sympatique. Celle-ci est faite en JS et CSS grâce à un bel outil (compatible IE et Firefox) créé par Dream Projections Inc. :
http://www.dreamprojections.com/SyntaxHighlighter/Default.aspx
Aucun commentaire:
Enregistrer un commentaire