Un court tutoriel sur XMLHttpRequest()

Gazette Linux n°123 — février 2006

par Bob SMITH (Copyright © 2006) bmsith@linuxtoys.org

traduction par Stéphane ROBERT(tous droits réservés) r.bob.stephane@gmail.com

relecture Jules CATOIS jules.catois@gmail.com


Introduction

Ce tutoriel va vous montrer comment créer une page web qui répond à un événement asynchrone. En 5 exercices simples, nous allons vous montrer la base d’une application Javascript et XML asynchrone. Vous allez devoir apprendre un peu de Javascript, mais il n’y aucune nécessité d’apprendre quelque chose sur XML. Notre but est de vous montrer comment créer une application web réactive en investissant un minimum de temps.

Ce que vous devrez déjà savoir : Vous devrez être familier avec la création de page web basique et avoir une idée générale de la nature des requêtes client/serveur d’une page web. Vous devrez aussi comprendre comment un programme CGI (interface de passerelle commune) fonctionne et avoir un peu d’expérience de programmation de ces derniers. Nous utilisons quelques lignes de PHP dans nos exercices, mais vous pouvez les remplacer par du C ou du Perl si vous le souhaitez.

Pré-requis pour les exemples : Pour faire les exercices de ce tutoriel, vous allez avoir besoin d’un navigateur web avec Javascript d’activé. Javascript est par défaut dans la plupart des navigateurs, donc cela ne devrait pas nécessiter d'action de votre part, sauf si vous l’avez désactivé précédemment. Vous allez avoir aussi besoin d’un serveur web qui supporte PHP et CGI, et la capacité de charger une page web sur ce dernier. Vous devriez être prêt à commencer si vous avez déjà Apache et PHP d’installés sur votre PC. En fait, nos exercices supposent que vous utilisiez votre PC comme serveur web.

Vue d’ensemble de l’application

Afin d'illustrer notre nécessité d’utiliser AJAX, Prenons un exemple concret de la vie réelle : nous avons construit un répondeur téléphonique et nous voulons que les informations de la personne qui appelle soit affichées sur une page web, qui soit consultable que nous soyons à la maison ou au travail. Le flot d’information de notre application ressemble à quelque chose comme ceci :

  (Répondeur -> syslog -> fifo -> Apache -> page web)
Notre répondeur va enregistrer les informations de la personne qui appelle via le protocole syslog en utilisant, LOG_LOCAL3, une fonction qui n’est utilisée par aucune autre application sur notre système et une règle syslog dans '/etc/syslog.conf' qui va transmettre les messages avec cette fonction à une file FIFO située dans le répertoire document d’Apache. Dans ce tutoriel, nous allons nous occuper d’obtenir les chaines de caractères depuis la FIFO jusqu’à la page web. Écrire dans une FIFO est une partie asynchrone de notre exemple d’application.

Pour commencer

Dans ce premier exercice nous allons tester l’environnement de développement en lançant une simple application PHP. Sauvegardez le programme suivant en tant que getfifo.php dans le répertoire de document de votre serveur web :

<?php
  $fp = fopen("ajaxfifo", "r");
  if ($fp) {
    $ajaxstring = fgets($fp, 128);
    fclose($fp);
  }

  header("Content-Type: text/html");
  print($ajaxstring);
?>
Maintenant créez une file FIFO dans ce même répertoire
mkfifo ajaxfifo
Essayez de voir getfifo.php en utilisant votre navigateur web. Il devrait se stopper, attendant de lire 'ajaxfifo' pour terminer. Ecrivez des données sur la FIFO avant que le navigateur ne s’interrompe.
echo "Hello, World" > ajaxfifo
Le texte que vous avez saisi devrait s’afficher proprement et vous pouvez passer à l'exercice suivant. Si les données n’apparaissent pas, faite machine arrière et vérifier que votre serveur web et PHP sont installés et fonctionne correctement.

DOM en deux lignes de code

Javascsript est un langage orienté objet et traite une page web affichée comme un objet. Le Document Objet Model ou DOM décrit le projet, ses propriétés, ses verbes (ou méthodes) disponibles dans Javascript. En utilisant le DOM, vous pouvez nommer différentes parties de votre page web et effectuer différentes actions sur ces parties.

L’exercice suivant vérifie que Javascript est activé sur votre navigateur en créant une section nommée sur une page web et en insérant du texte dans cette section, copier le programme suivant en le nommant hello.html dans le répertoire document de votre serveur web :

<html>
<head>
<title>Exercice 2: Utiliser DOM pour tester Javascript</title>

<script language=javascript type="text/javascript">
<!-- Hide script from non-JavaScript browsers

  // SayHello() affiche un message dans la section "hello" du document
  function SayHello() {
    document.getElementById("hello_area").innerHTML="Hello, World";
    return;
  }

-->
</script>
</head>

<body onload="SayHello()">
<h3><center>Exercice 2: Utiliser DOM pour tester Javascript</center></h3>
</p>
<div id="hello_area">Ce texte est remplacé.</div>
</body>
</html>
Le code ci-dessus définit une section de la page web comme "hello_aera" et utilise le sous programme SayHello pour insérer le texte dans cette section. Chargez hello.html et vérifier que la Javascript de votre navigateur affiche "Hello world" sur votre page web.

Les callbacks dans JavaScript

Un callback (rappel) est un sous-programme qui est appelé quand un événement particulier se produit. Javascript a un nombre conséquent d’événements auxquels vous pouvez associer un callback. Le programme suivant démarre un minuteur en utilisant un callback qui est invoqué quand la page est chargée. Copiez ce programme en tant que callback.html dans le répertoire document de votre serveur et vérifiez que le minuteur est mis à jour sur votre page web toutes les deux secondes.
<html>
<head>
<title>Exercice 3: Exemple d'un callback Javascript</title>

<script language=javascript type="text/javascript">
<!-- Hide script from non-JavaScript browsers
  var count;
  count = 0;

  // Affiche le compte actuel sur la page
  function DisplayCount() {
    // Affiche le temps actuel dans la section "count" de la page web
    document.getElementById("count_area").innerHTML=
      "Le compte est de : " + count++;

    // Prépare le prochain appel de DisplayCount
    setTimeout("DisplayCount()", 2000);
    return;
  }
-->
</script>
</head>

<body onload="DisplayCount()">
<h3><center>Exercice 3: Exemple d'un callback Javascript</center></h3>
<div id="count_area">Ce texte est remplacé.</div>
</body>
</html>

Comment utiliser XMLHttpRequest()

XMLHttpRequest est un sous programme Javascript qui vous laisse faire une requête http et associer un callback à la réponse. Comme la réponse a un callback, le navigateur est libre de répondre aux entrées de l’utilisateur. D’une certaine façon, XMLHttpRequest est à javacript ce que select est au C – Un moyen d’attendre un événement. XMLHttpRequest() est ce qui permet d’avoir le ‘A’ dans AJAX.

L’exercice suivant ajoute seulement XMLHttpRequest() aux exemples vu précédemment. Nous demandons les données provenant de getfifo.php en utilisant XMLHttpRequest, et en associant un callback, à l’arrivée de la réponse. La callback de la réponse affiche les données en utilisant une section nommée par le DOM. Copiez le code suivant en tant que async.html:

<html>
<head>
<title>Exercice 4: Un exemple de XMLHttpRequest() </title>

<script language=javascript type="text/javascript">
<!-- Hide script from non-JavaScript browsers

  var req_fifo;

  // GetAsyncData envoie une requête pour lire la FIFO.
  function GetAsyncData() {
    url = "getfifo.php";

    // section pour les objets XMLHttpRequest natifs
    if (window.XMLHttpRequest) {
      req_fifo = new XMLHttpRequest();
      req_fifo.abort();
      req_fifo.onreadystatechange = GotAsyncData;
      req_fifo.open("POST", url, true);
      req_fifo.send(null);
    // section pour AtiveX de IE/Windows
    } else if (window.ActiveXObject) {
      req_fifo = new ActiveXObject("Microsoft.XMLHTTP");
      if (req_fifo) {
        req_fifo.abort();
        req_fifo.onreadystatechange = GotAsyncData;
        req_fifo.open("POST", url, true);
        req_fifo.send();
      }
    }
  }

  // GotAsyncData est le callback de lecture pour l'appel de XMLHttpRequest() ci-desssus.
  // Cette procédure n'est executée que si des données sont obtenues par la requête.
  // Nous mettons à jour la section "fifo_aera" sur la page quand les données arrivent
  function GotAsyncData() {
    // seulement si req_fifo affiche "loaded"
    if (req_fifo.readyState != 4 || req_fifo.status != 200) {
      return;
    }
    document.getElementById("fifo_data").innerHTML=
      req_fifo.responseText;

    // Prépare le prochaine appel pour attendre les données de la file FIFO.
    setTimeout("GetAsyncData()", 100);
    return;
  }

-->
</script>

</head>
<body onload="GetAsyncData()">
<h3>Exercice 4: Un exemple de XMLHttpRequest()</h3><p>
<div id="fifo_data"> </div>

</body>
</html>
Chargez async.html et, si tout se passe bien, tout ce qui est envoyé à ajaxfifo devrait apparaitre sur la page web. Par exemple :
echo "Hello, AJAX" > ajaxfifo
Prise d'écran Exercice 4

Une application Web

Si vous voulez faire une application (comme notre répondeur), vous voudrez que votre interface web réponde aux événements se produisant dans l’application, les exercices précédents vous ont montré comment le faire. Mais vous voudriez peut-être aussi que l’interface de votre application possède un certain nombre de contrôle disponible pour l’utilisateur. Le dernier exercice ci-dessous ajoute du code à l’exercice précédent pour vous montrer comment lier des boutons d’un formulaire de page web à des sous programmes Javascript. Cet exercice va démontrer qu’une interface web peut attendre un événement asynchrone tout en restant interactive.

Copiez async.html sur un fichier nommé webui.html et ajoutez le sous-programme suivant au code Javascript :

// setColor met à jour la section "color_area" avec la couleur spécifiée
  function setColor(new_color) {
    color_text = "<table border=2 bgcolor=";
    if ("Blue" == new_color) {
      color_text += "\"Blue\">"
    }
    else if ("Red" == new_color) {
      color_text += "\"Red\">"
    }
    else {       // shouldn't get here
      color_text += "\"Green\">"
    }
    color_text += "<tr><td>A little color</td></tr></table>";
    document.getElementById("color_area").innerHTML=color_text;
  }
Ajouter un formulaire dans la partie HTML de webui.html.
<body onload="GetAsyncData()">
<h3>Exercise 5: A Trivial Web UI</h3><p>
<div id="fifo_data"> </div>
<p>
<div id="color_area">No color yet.</div><p>
<form>
<input type=button value="Blue" onClick="setColor('Blue')">
<input type=button value="Red" onClick="setColor('Red')">
</form>
</body>

Résumé et Notes

Dans ce court tutoriel nous avons exploré les notions fondamentales pour construire une interface web réactive et interactive utilisant Javascript et XMLHttprequest. Dans le but de se concentrer sur les concepts majeurs nous avons ignoré un nombre important de détail, comme la gestion d’erreur et le retour de code. Néanmoins vous pouvez ajouter les techniques vues dans cet article à votre connaissance web.

FIFO contre /dev/fanout: Ouvrez deux pages web affichant async.html et écrivez des données dans la file FIFO. Notez que les données que vous avez écrites n’apparaîtront que dans une seule page. Ceci est dû au fait que la FIFO n’envoie les infos qu’à un seul lecteur. Dans une véritable application, nous devrons utiliser un dispositif fanout pour que les données écrites aillent à tous les lecteurs. Fanout est décrit dans un article précédant de la gazette linux ainsi que sur la page de l’auteur.

XML: Si vous voulez obtenir seulement un seul morceau de donnée de votre serveur web, vous pouvez utiliser le code dans cette article, Mais dès que vous demandez plus d’un morceau de donnée vous devriez changer pour XML. Cela n’est pas forcément compliqué.

Par exemple, disons que vous avez modifié getfifo.php pour utiliser l’identifiant de celui qui appelle pour chercher quand s’est produit et combien de temps a duré le dernier appel. Et vous voulez retourner cette information avec la chaine de caractère désignant l’identifiant de celui qui appelle. Le code PHP pour construire la réponse XML pour les trois morceaux de donnée peut ressembler à ceci :

<?php
  header("Content-Type: text/xml");
  print("<?xml version=\"1.0\" ?>\n");
  print("<caller_info>\n");
  printf("<caller_id>%s</caller_id>\n",       "Mary");
  printf("<lastcalltime>%s</lastcalltime>\n", "10:24 am");
  printf("<lastcalldur>%s</lastcalldur>\n",   "12:05");
  print("</caller_info>\n");
?>
Au lieu d’utiliser req_fifo.responsetext pour obtenir tout le corps de la réponse, vous pouvez utiliser ceci pour extraire chacun des trois champs que vous désirez.
  callid = req_fifo.responseXML.getElementsByTagName("caller_id");
  calltm = req_fifo.responseXML.getElementsByTagName("lastcalltime");
  calldur = req_fifo.responseXML.getElementsByTagName("lastcalldur");
  callid[0].childNodes[0].nodeValue;

  document.getElementById("caller_data").innerHTML=
    callid[0].childNodes[0].nodeValue;
  document.getElementById("lastcalltime").innerHTML=
    calltm[0].childNodes[0].nodeValue;
  document.getElementById("lastcalldur").innerHTML=
    calldur[0].childNodes[0].nodeValue;
Il y a des façons plus simples de faire ça, mais le code ci-dessus devrait vous donner une idée de comment faire.

Sources utiles Le site web des développeurs d’Apple a un bon article sur XMLHttprequest, vous pouvez le trouver ici
http://developer.apple.com/internet/webcontent/xmlhttpreq.html

Vous trouverez les tutoriels du site web javascript kit d’une grande aide si vous désirez étendre vos connaissances acquise grâce à cet article : vous pouvez trouver leurs tutoriels ici :
http://www.javascriptkit.com/javatutors/

Le site Web IBM developerWorks a de très bon articles sur AJAX et XML nous trouvons celui-ci particulièrement utile :
http://www.ibm.com/developerworks/web/library/wa-ajaxintro1.html

Pour terminer, vous pouvez être intéressé par le répondeur à faible coût qui est cœur de cette application :
http://www.linuxtoys.org/answer/answering_machine.html


Bob Smith

Bob est un passionné d'électronique et un programmeur Linux, il est l'un des auteurs de "Linux Appliance Design" publié par No Starch Press


Adaptation française de la Gazette Linux

L'adaptation française de ce document a été réalisée dans le cadre du Projet de traduction de la Gazette Linux

Cet article est publié selon les termes de la Open Publication License. La Linux Gazette n'est ni produite, ni sponsorisée, ni avalisée par notre hébergeur principal, SSC, Inc.

Vous pourrez lire d'autres articles traduits et en apprendre plus sur ce projet en visitant notre site http://www.traduc.org/Gazette_Linux

Si vous souhaitez apporter votre contribution, n'hésitez pas à nous rejoindre, nous serons heureux de vous accueillir.