fetch()
fetch() est une fonction JavaScript utilisée pour récupérer, de manière asynchrone, des ressources sur un réseau. Son 1er argument (obligatoire) est l'URL offrant la ressource à récupérer. Le 2nd argument est optionnel mais permet de personnaliser la requête (ou d'effectuer les réglages sur le corps de la requête).
Une lecture de la page d'introduction : "les promesses" est indispensable pour la compréhension de ce billet.
Le rendu de cette fonction "fetch" est un objet (nommé : promesse) qui a 3 états :
pending : en cours ;
fulfilled : terminé (sans erreur) ;
rejected : rejeté.
Dans les extraits de code ci-dessous, fetch est utilisée avec son seul argument obligatoire, une URL :
fetch('https://code.dhumbert.info/json/demo.json')
fetch("http://localhost/crud.php?op=create&studentName=Pierre&course=informatique");
Dans le 1er extrait, l'URL n'a pas de paramètre. Dans le second, elle en a 3 qui sont dans l'ordre :
"op" de valeur "create" ;
"studentName" de valeur "Pierre" ;
"course" de valeur "informatique".
Dans les extraits de code ci-dessous, fetch est utilisée avec,en gras, un argument optionnel de réglage :
fetch(
"http://localhost/crud.php",
{
method: "POST",
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
'op': 'create',
'studentName' :'Pierre",
'course': 'informatique',
})
}
)
Dans l'extrait de code ci-dessus, 3 paires "clé, valeur" caractérisent le réglage :
la clé "method" prend les plus souvent les valeurs "POST" ou "GET" ;
la clé "headers" définit le type d'encodage des données transmises ;
la clé "body" contient par exemple les "variables" de la requête (mise au format JSON dans cet exemple).
1. La promesse :
La promesse (ie : le rendu de la fonction fetch) est un objet qui possède, entre autre, les méthodes "then()" et "catch()" qui permettent de "manipuler" la valeur de sa propriété interne "result".
Accès à la documentation complète.
Le 1er paramètre de "then()" est une fonction qui a comme seul argument le résultat produit par "fetch()" en cas de réussite.
Le 2nd paramètre est optionnel. Lorsqu'il est présent, c'est une fonction dont le seul argument est l'erreur produite par fetch() en cas d'échec.
then() renvoie une promesse. Il est donc possible, comme le montre le paragraphe suivant, d'enchainer (le chainage) plusieurs méthodes "then" pour, par exemple, affiner le traitement de la réponse à nos besoins.
Accès à la documentation complète.
Le paramètre de "catch()" est une fonction qui a comme seul argument la valeur l'erreur produite par "fetch()" lors de l'échec.
"catch()" permet donc la gestion des erreurs (NB : lorsqu'une erreur est détectée, "then()" est ignorée).
2. Gestion de la réponse :
Le fichiers figurant dans les onglet "demo.json" et "testdh.html" au bas de cette page sont stockées sur un serveur respectivement aux adresses :
La fonction test() du script permet la récupération d'une partie du contenu du fichier "demo.json", partie qui sera affichée dans le paragraphe identifié "resu" de la page web. Elle est reproduite ci-dessous :
async function test() {
const res = await fetch('json/demo.json')
.then( (response) => {
if (response.ok) {
return response.json();
}
else {
throw new Error("Erreur de chargement :", {cause: response});
}
})
.then (responseJSON => responseJSON.results)
.catch( error => console.error(error) );
//
const diva = document.getElementById("resu");
diva.innerHTML = JSON.stringify(res);
return;
}
Dans ce code, la méthode "then" est appliquée une 1ère fois pour convertir la réponse promise "response" au format JSON par la méthode json(), puis une 2ème fois sur l'objet converti "responseJson" est en extraire la valeur de la clé "results" et le rendre dans la constante res.
En résumé :
En cas de succès, "fetch()" rends une valeur (ici au format JSON) qui sera l'argument de ma 1ère fonction fléchée. J'ai identifié cet argument sous le nom "response" dans la 1ère application de la méthode "then()" ;
Cette 1ère application de "then" rends une nouvelle promesse dont j'utilise le réponse comme argument de ma 2ème fonction fléchée. J'ai identifié cet argument sous le nom "responseJSON" dans la 2ème application de la méthode "then()" ;
Cette 2ème application de "then" rends une nouvelle promesse dont la valeur de retour est celle de la clé "results" de l'objet "responseJSON".
La constante "res" reçoit donc cette valeur ;
Celle-ci est finalement linéarisée par JSON.stringify () pour être affichée dans la page.
Voir la documentation https://developer.mozilla.org/fr/docs/Web/JavaScript/Guide/Using_promises et l' utilisation des fonctions fléchées pour alléger la syntaxe des fonctions de rappel utilisées.
Il n'est pas obligatoire de changer l'identifiant de l'argument de "then()" à chaque appel. Par exemple, le code ci-dessous utilise systématiquement la notation "u" pour identifier l'argument de "then()". Il produit exactement les mêmes résultats mais est absolument illisible et donc peu facile à maintenir.,
const res = fetch('https://code.dhumbert.info/json/demo.json')
.then( (u) => {
if (u.ok ) {
return u.json();
} else {
throw new Error ("Erreur de chargement : , {cause : u}
}
})
.then( u =>u.results)
.catch( u=> console.error(u) );
alert ( JSON.stringify (res));
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TestDH</title>
<link rel="stylesheet" href="testdh.css">
</head>
<body>
<div id="test"></div>
<h1>Test en cours</h1>
<div id="resu"></div>
<!--script src="command.js"-->
<script>
async function test() {
const res = await fetch('json/demo.json')
.then( (response) => {
if (response.ok) {
return response.json();
}
else {
throw new Error("Erreur de chargement :", {cause: response});
}
})
.then (responseJSON => responseJSON.results)
.catch( error => console.error(error) );
//
const diva = document.getElementById("resu");
diva.innerHTML = JSON.stringify(res);
return;
}
//
test();
</script>
</body>
</html>
{
"count":2,
"results":[
{
"name":"bulbasaur",
"url":"https://pokeapi.co/api/v2/pokemon/1/"
},
{
"name":"ivysaur",
"url":"https://pokeapi.co/api/v2/pokemon/2/"
}
]
}