Chapitre 7 : Fetch et JSON
1 min de lecture
Chapitre 7 : Fetch et JSON
Objectif
À la fin de ce chapitre, la page demande fiche.json à une adresse http://, attend la réponse, puis affiche le titre et le texte de ce fichier. Si l’adresse ne répond pas, le paragraphe de la fiche affiche « L’adresse ne répond pas. ». Le dossier premiere-page reste en place. phraseEssai, prenoms, phrases, essai et les deux getElementById du message et du bouton ne changent pas. L’écouteur reste function (), sans parenthèses d’appel et sans console.log.
Servir le dossier
Ouvrir index.html depuis le disque donne une adresse file://. fetch demande un document, et cette adresse refuse la demande. Il faut une adresse http://.
Dans un terminal, placez-vous dans premiere-page et lancez :
python3 -m http.server 8000
Laissez ce terminal ouvert. Dans le navigateur, ouvrez http://127.0.0.1:8000/. Vous voyez « En attente d’un clic. » et le bouton « Nouvel essai ». Un clic affiche « Aina, essai 1 sur 3. ».
Si le terminal dit que le port est déjà pris, relancez avec 8001 et ouvrez http://127.0.0.1:8001/. Ctrl+C arrête le serveur. La page ne peut alors plus se recharger : le HTML lui-même n’arrive pas. Relancez la commande avant la suite.
La fiche
Ajoutez deux paragraphes dans index.html, au-dessus de message. Le clic ne les lit pas. La balise script reste en bas, après le bouton.
<p id="titre">Chargement…</p>
<p id="fiche">La fiche n’est pas encore arrivée.</p>
<p id="message">En attente d’un clic.</p>
<button type="button" id="action">Nouvel essai</button>
Créez fiche.json dans le même dossier. Les noms et les textes sont entre guillemets droits ", comme dans le script. Une virgule sépare les deux lignes. Il n’y a pas de virgule après la dernière, ni de commentaire.
{
"titre": "Les essais",
"texte": "Trois essais sont permis."
}
Rechargez http://127.0.0.1:8000/. « Chargement… » et « La fiche n’est pas encore arrivée. » restent en place : le script ne lit pas encore le fichier.
Demander sans bloquer le clic
Dans script.js, après les getElementById du message et du bouton, lisez les deux nouveaux paragraphes. Placez fetch avant l’écouteur. Cet écouteur reste la dernière instruction, avec function ().
const titre = document.getElementById("titre");
const fiche = document.getElementById("fiche");
fetch("fiche.json").then(function (reponse) {
if (reponse.ok === false) {
titre.textContent = "Fiche indisponible";
fiche.textContent = "L’adresse n’a pas renvoyé la fiche.";
return;
}
return reponse.json();
}).then(function (donnees) {
if (!donnees) {
return;
}
titre.textContent = donnees.titre;
fiche.textContent = donnees.texte;
}).catch(function () {
titre.textContent = "Fiche indisponible";
fiche.textContent = "L’adresse ne répond pas.";
});
"fiche.json" est relatif. Le navigateur le complète avec l’adresse de la page, donc http://127.0.0.1:8000/fiche.json. fetch lance la demande et rend la main. La fonction passée à then attend qu’une réponse arrive. L’écouteur est posé avant cette réponse.
Ajoutez ce journal sur la première ligne du premier then, avant le if.
console.log("La réponse est là.");
Ajoutez l’autre juste après le point-virgule qui clôt catch, avant l’écouteur.
console.log("Le script continue.");
Rechargez. La console affiche d’abord « Le script continue. », puis « La réponse est là. ». Retirez les deux console.log.
Rechargez encore. Le titre affiche « Les essais ». La fiche affiche « Trois essais sont permis. ». Le premier clic affiche « Aina, essai 1 sur 3. ». La réponse écrit dans titre et fiche. Le clic écrit dans message.
La propriété, pas l’objet entier
reponse.ok vaut true pour un statut 200. reponse.json() transforme le texte du fichier en objet. Cette lecture attend aussi : le then suivant reçoit donnees. donnees.titre vaut "Les essais" et donnees.texte vaut "Trois essais sont permis.".
Remplacez donnees.titre par donnees. Rechargez. Le titre affiche [object Object]. textContent a reçu l’objet, pas la chaîne "Les essais". Remettez donnees.titre.
Écrivez donnees.titres, avec un s de trop, et ajoutez au-dessus console.log(donnees.titres). Rechargez. La console affiche undefined : ce nom est absent du fichier. Le titre se vide, « Chargement… » disparaît, et la fiche affiche encore « Trois essais sont permis. ». Retirez le journal, rétablissez donnees.titre. « Les essais » revient.
404 : le serveur a répondu
Ajoutez console.log(reponse.status) sur la première ligne du premier then. Dans fetch, demandez "fiche-absente.json". Rechargez. La console affiche 404. Le serveur a répondu que le fichier n’existe pas. reponse.ok vaut false, donc catch ne part pas. La page affiche « Fiche indisponible » et « L’adresse n’a pas renvoyé la fiche. ».
Ce return ne transmet pas d’objet. Le then suivant reçoit undefined, et if (!donnees) sort avant donnees.titre. Retirez ce if et son return, gardez le fichier absent, rechargez. donnees vaut undefined, donc donnees.titre échoue, et catch écrit « L’adresse ne répond pas. » à la place de la phrase du 404. Remettez le if, remettez "fiche.json", retirez le console.log. « Les essais » revient.
Aucune réponse, ou un JSON illisible
Le serveur du dossier doit rester lancé, sinon index.html ne s’ouvre plus. Changez seulement l’adresse demandée.
fetch("http://127.0.0.1:5999/fiche.json")
La page vient encore de http://127.0.0.1:8000/. Rien n’écoute sur le port 5999. Remplacez le catch par celui-ci.
}).catch(function (erreur) {
console.log(erreur.name);
titre.textContent = "Fiche indisponible";
fiche.textContent = "L’adresse ne répond pas.";
});
Rechargez. La console affiche TypeError. Le titre devient « Fiche indisponible », la fiche « L’adresse ne répond pas. ». Le clic affiche toujours « Aina, essai 1 sur 3. » : l’écouteur a été posé avant l’échec de la demande.
Remettez fetch("fiche.json") et gardez le journal. Rechargez http://127.0.0.1:8000/ : la fiche correcte revient, sans TypeError. Un double-clic sur index.html ouvre une adresse file://. La demande est refusée, la console affiche TypeError, et la fiche montre « L’adresse ne répond pas. ». Revenez à l’adresse http://.
Effacez le guillemet fermant de "Les essais dans fiche.json, enregistrez, rechargez la page servie en http://. Le serveur répond 200. reponse.json() ne peut pas lire ce texte : la console affiche SyntaxError, et la fiche montre encore « L’adresse ne répond pas. ». Le nom de l’erreur sépare ce cas du port fermé. Rétablissez le guillemet, retirez console.log(erreur.name) et le paramètre. catch redevient function (). Au rechargement, « Les essais » et « Trois essais sont permis. » sont de retour.
Exercice
- Avec le serveur lancé, ouvrez
http://127.0.0.1:8000/. Le titre est « Les essais », la fiche « Trois essais sont permis. », le premier clic « Aina, essai 1 sur 3. ». - Demandez
fiche-absente.json, puis rechargez. La fiche affiche « L’adresse n’a pas renvoyé la fiche. ». Remettezfiche.json. - Demandez
http://127.0.0.1:5999/fiche.json, puis rechargez. La fiche affiche « L’adresse ne répond pas. ». Remettezfetch("fiche.json"). - Retirez un guillemet dans
fiche.json, rechargez, puis réparez le fichier. Le titre redevient « Les essais ». Le script final n’a aucunconsole.log.
À retenir
fetchdemandefiche.jsonenhttp://. Le serveur lancé danspremiere-pagelivre la page et la fiche.- La fonction de
thenattend la réponse. L’écouteur du clic est posé avant elle. - Un statut 404 est une réponse.
reponse.okvautfalse, etreturnévite de lire un objet qui n’est pas arrivé. - Sans réponse, avec une adresse
file://, ou avec un JSON illisible,catchécrit « L’adresse ne répond pas. » dans la page. donnees.titreetdonnees.textesont les deux chaînes du fichier. L’objet entier s’affiche comme[object Object].
La suite
La page sait demander une fiche, attendre, et montrer un message quand l’adresse ne répond pas. Tout tient encore dans script.js : les variables, phraseEssai, quatre getElementById, le fetch, puis l’écouteur. Le chapitre 8, « Modules et organisation du code », répartira ce script dans plusieurs fichiers. Chaque fichier n’exposera que ce que les autres ont le droit d’appeler, et la page chargera le point d’entrée. Gardez premiere-page, fiche.json et ce fetch. phraseEssai, prenoms, phrases et essai restent tels quels. L’écouteur reste function (), sans parenthèses d’appel et sans console.log.