Nous allons voir dans ce cours comment envoyer et recevoir des données avec le protocole HTTP à l’aide de JavaScript.
1 - Synchrone ou Asynchrone ?
Voilà le dilemme ? Mais essayons tout d’abord de comprendre ces termes.1.1 - Synchrone
Une requête synchrone va bloquer le déroulement de l’exécution du code jusqu’à l’obtention d’un code de réponse de la part du serveur et ce quelque soit le résultat de la requête; succès ou échec.1.2 - Asynchrone
Lors d’une requête asynchrone, l’application continuera de d’exécuter votre code. Des écouteurs seront mis en place afin de détecter un changement d’état de la requête et d’agir en conséquence, comme par exemple exécuter une fonction particulière si la requête est terminée ou si cette dernière a échoué.2 - L’objet XMLHttpRequest()
2.1 - Instancier XMLHttpRequest
Pour réaliser une requête HTTP, nous devons tout d’abord instancier l’objet XMLHttpRequest
const req = new XMLHttpRequest();
Jusqu’à là, ça va ? Alors continuons...2.2 - Ouvrir la requête
Nous allons utiliser la méthode open() de XMLHttpRequest afin de définir la méthode et l’url de notre requête.
req.open('GET', 'http://www.neore.fr/mon_fichier.txt', false);
La méthode accepte 5 arguments dont les 2 premiers sont impératifs :
- Le type de méthode : GET, POST, PUT, DELETE, etc
- L’url : l’adresse absolue du fichier concerné.
- async : (true ou false) afin de préciser si la requête est asynchrone ou non, elle l’est pas défaut.
- user : Lors d’une connexion nécessitant une authentification, nous pouvons préciser le nom de l’utilisateur
- password : Lors d’une connexion nécessitant une authentification, nous pouvons préciser le mot de passe
2.3 - Executer la requête
Tout est prêt, nous pouvons maintenant envoyer notre requête grâce à la méthode send()
req.send(null);
Mais Laurent, pourquoi on met null en argument de cette méthode ?En voilà une bonne question ! Et bien XMLHttpRequest peut tout autant recevoir que envoyer des données. Lors de l’envoi de données, avec la méthode POST par exemple, nous passerons les données envoyées en argument de la méthode send().
Dans le cas présent, nous n’envoyons aucune donnée, donc nous indiquons simplement null.
3 - Traitement du résultat d’une requête
3.1 - Les propriétés importantes de XMLHttpRequest
3.3.1 - XMLHttpRequest.status
La propriété status contient le code de réponse du serveur Http correspondant à la requête que nous avons formulé. Nous pouvons noter quelques codes importants :- 200 : Tout va bien, requête OK
- 404 : Le fichier demandé n’existe pas... un classique.
- 500 : Erreur d’execution du serveur.. un classique lors d’un problème d’execution de script Php par exemple
3.3.2 - XMLHttpRequest.statusText
La propriété statusText contient une chaîne de caractères retournée par le serveur pour nous expliquer un peu mieux le code de résultat. Cette chaîne peut contenir des informations pertinentes pour débugger.3.3.3 - XMLHttpRequest.responseText
La propriété responseText contient le contenu de la réponse du serveur sous la forme d'une chaîne de caractères.3.2 - Testons le résultat de notre requête
Notre requête est envoyée et nous attendons donc le résultat...(rappelez vous, nous avons initialisé une requête synchrone).Une fois le résultat de la requête reçu nous pouvons tester le status de celle-ci et, si tout va bien, récupérer le contenu de la requête.
if (req.status === 200) {
// Yeah ! Super, nous avons un code de réponse OK
// Voyons le contenu de la réponse dans la console :
console.log(req.responseText);
} else {
// Crénom d’un vieux mérou, y’a une .ouille dans le potage !
// Nous n’avons pas eu un code de réponse OK, mais un autre...
// Voyons ça dans la console
console.log("Code de réponse :", req.status);
// Avec un peu plus d’info :
console.log("Code de réponse :", req.statusText);
}
Nous vérifions donc que req.status est bien égal à 200. Dans le cas contraire, nous affichons le code de résultat et un peu plus d'info dans la console.4 - Création d'une requête asynchrone
4.1 - Instancier XMLHttpRequest
const req = new XMLHttpRequest();
Vous voilà en terrain connu maintenant. Bravo !4.2 - Préparons le terrain avec quelques fonctions sympathiques
4.2.1 - Traiter la progression de la requête : XMLHttpRequest.onprogress()
Nous allons créer une fonction qui affichera la progression de téléchargement de notre requête.
function maProgression(event) {
// L'argument event va contenir deux propriétés intéressantes :
// event.loaded : nous indique la quantité de d'octets téléchargés.
// event.total : la quantité d'octets totale attendue.
// Nous affichons ça dans la console.
// MAIS, MAIS, MAIS !!! Au préalable nous allons vérifier que des données
// existent sinon nous aurons une belle erreur d'execution.
if (event.lengthComputable) {
console.log("Données totales : ", event.total);
console.log("Données reçues : ", event.loaded);
} else {
console.log("Pas de données calculables");
}
}
req.onprogress = maProgression;
// Ceci n'est pas un appel direct de la fonction mais bien une référence à la fonction à appeler quand l'événement se produira
4.2.2 - Traiter une erreur de la requête : XMLHttpRequest.onerror()
Nous allons créer une fonction qui affichera le pourquoi d'une erreur en cas d'erreur.
function monErreur(event) {
// Cette fonction sera appellée uniquement en cas d'erreur de la requête.
// Il nous suffit d'indiquer l'erreur dans la console pour en savoir plus.
console.error("Erreur", event.target.status);
}
req.onerror = monErreur; // Ceci n'est pas un appel direct de la fonction mais bien une référence à la fonction à appeler quand l'événement se produira
4.2.3 - Traiter le changement de statut de la requête : XMLHttpRequest.onload()
Nous allons créer une fonction qui sera executée à chaque changement de statut de la requête. Si nous recevons le code 200, nous pourrons afficher le contenu de la réponse.
function enCours(event) {
// On teste directement le status de notre instance de XMLHttpRequest
if (this.status === 200) {
// Tout baigne, voici le contenu de la réponse
console.log("Contenu", this.responseText);
} else {
// On y est pas encore, voici le statut actuel
console.log("Statut actuel", this.status, this.statusText);
}
}
req.onload = enCours;// Ceci n'est pas un appel direct de la fonction mais bien une référence à la fonction à appeler quand l'événement se produira
4.3 - Ouvrir la requête asynchrone
req.open('GET', 'http://www.neore.fr/mon_fichier.txt', true);
Nous avons donc défini le dernier argument à true afin de préciser que nous sommes bien en mode asynchrone.4.4 - Lancement de la requête
req.send(null);
- Laurent, pourquoi y'a null comme argument ?
- Ben mon p'tit Loulou fallait pas roupiller au début du cours, allez, tu relis le début, hop, hop, hop.
4.5 - Tester si la réponse est bien au format json avec l'objet JSON et la méthode parse
try { JSON.parse('{}'); // {} JSON.parse('true'); // true JSON.parse('"toto"'); // "toto" JSON.parse('[1, 5, "false"]'); // [1, 5, "false"] JSON.parse('null'); // null } catch (e) { console.error("Parsing error:", e); }
Exercices pratiques
Exercice 1 : Afficher le contenu d'une réponse dans un conteneur html
Objectif : Vous devez traiter XMLHttpRequest.responseText afin de remplir un conteneur div ayant pour id "ma_div".Pour cela, vous devrez :
- Créer une div avec l'id demandé dans votre code HTML.
- Instancier XMLHttpRequest
- Créer une requête GET pour l'url : http://www.neore.fr/mon_fichier.txt
- Tester le code de retour de la requête
- Traiter le contenu de la réponse
- Définir le contenu de votre div avec le contenu de la réponse
Exercice 2 : Envoyer des données et traiter la réponse
Objectif : Vous devrez envoyer des données avec la méthode POST et traiter XMLHttpRequest.responseText afin de remplir un conteneur div ayant pour id "ma_div2".Pour cela, vous devrez :
- Créer une div avec l'id demandé dans votre code HTML.
- Instancier XMLHttpRequest
- Créer une requête POST pour l'url : http://www.neore.fr/coucou.php
- Envoyer les données nom=votre_prenom (remplacer votre_prenom par votre vrai prénom
- Tester le code de retour de la requête
- Traiter le contenu de la réponse
- Définir le contenu de votre div avec le contenu de la réponse