JavaScript peut envoyer des requtes rseau au serveur et charger de nouvelles informations chaque fois que ncessaire.
Par exemple, nous pouvons utiliser une requte rseau pour :
- Soumettre une commande,
- Charger des informations utilisateur,
- Recevoir les dernires mises jour du serveur,
- etc.
Et tout cela sans recharger la page !
Il y a un terme gnrique AJAX (abrg de Asynchronous JavaScript And XML) pour les requtes rseau partir de JavaScript. Cependant nous navons pas besoin dutiliser XML : le terme vient de lancien temps, cest pourquoi ce mot est l. Vous avez peut-tre dj entendu ce terme.
Il existe plusieurs faons denvoyer une requte rseau et dobtenir des informations du serveur.
La mthode fetch() est moderne et polyvalente, nous allons donc commencer avec celle-ci. Elle nest pas prise en charge par les anciens navigateurs (peut tre polyfilled), mais trs bien prise en charge par les navigateurs modernes.
La syntaxe de base est :
let promise = fetch(url, [options])
urllURL cible.optionsparamtres facultatifs : mthode, en-ttes, etc
Sans options, cest une simple requte GET, tlchargeant le contenu de lurl.
Le navigateur dmarre la requte immdiatement et renvoie une promesse que le code appelant devrait utiliser pour obtenir le rsultat.
Obtenir une rponse est gnralement un processus en deux tapes.
Premirement, la promise, renvoye par fetch, se rsout avec un objet de la classe intgre Response ds que le serveur rpond avec des en-ttes.
ce stade, nous pouvons vrifier ltat HTTP, pour voir sil est russi ou non, vrifier les en-ttes, mais nous ne disposons pas encore du corps.
La promesse rejette si le fetch na pas pu faire de requte HTTP, par exemple problmes de rseau, ou si ladresse nexiste pas. Les statuts HTTP anormaux, tels que 404 ou 500, ne provoquent pas derreur.
Nous pouvons voir ltat HTTP dans les proprits de rponse :
statusCode dtat HTTP, par exemple 200.okboolen,truesi le code dtat HTTP est 200-299.
Par exemple :
let response = await fetch(url);
if (response.ok) { // if HTTP-status is 200-299
// obtenir le corps de rponse (la mthode explique ci-dessous)
let json = await response.json();
} else {
alert("HTTP-Error: " + response.status);
}
Deuximement, pour obtenir le corps de la rponse, nous devons utiliser un appel de mthode supplmentaire.
Response fournit plusieurs mthodes bases sur les promesses pour accder au corps dans diffrents formats :
response.text()lit la rponse et retourne sous forme de texte,response.json()analyse la rponse en JSON,response.formData()retourne la rponse en tant que objetFormData(expliqu dans le chapitre suivant),response.blob()retourne la rponse en tant que Blob (donne binaire avec type),response.arrayBuffer()retourne la rponse en tant que ArrayBuffer (reprsentation de bas niveau de donne binaire),- aditionellement,
response.bodyest un objet ReadableStream, qui permet de lire le corps morceau par morceau, nous verrons un exemple plus tard.
Par exemple, obtenons un objet JSON avec les derniers commits de GitHub :
let url = 'https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits';
let response = await fetch(url);
let commits = await response.json(); // lire le corps de rponse et analyser en JSON
alert(commits[0].author.login);
Ou, la mme chose sans await, en utilisant la syntaxe des promesses pures :
fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits')
.then(response => response.json())
.then(commits => alert(commits[0].author.login));
Pour obtenir la rponse en texte, await response.text() au lieu de .json() :
let response = await fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits');
let text = await response.text(); // lire le corps de la rponse sous forme de texte
alert(text.slice(0, 80) + '...');
En tant que vitrine pour la lecture au format binaire, rcuprons et affichons une image du logo de fetch specification (voir le chapitre Blob pour plus de dtails sur les oprations de Blob):
let response = await fetch('/article/fetch/logo-fetch.svg');
let blob = await response.blob(); // tlcharger en tant qu'objet Blob
// create <img> for it
let img = document.createElement('img');
img.;
document.body.append(img);
// l'afficher
img.src = URL.createObjectURL(blob);
setTimeout(() => { // le cacher aprs 3 secondes
img.remove();
URL.revokeObjectURL(img.src);
}, 3000);
Nous ne pouvons choisir quune seule mthode de lecture du corps.
Si nous avons dj la rponse avec response.text(), alors response.json() ne fonctionnera pas, car le contenu du corps a dj t trait.
let text = await response.text(); // corps de la rponse consomm
let parsed = await response.json(); // echec (dj consomm)
En-ttes de rponse
Les en-ttes de rponse sont disponibles dans un objet den-ttes de type Map-like response.headers.
Ce nest pas exactement un Map, mais il a des mthodes similaires pour obtenir des en-ttes individuels par nom ou les parcourir :
let response = await fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits');
// get one header
alert(response.headers.get('Content-Type')); // application/json; charset=utf-8
// iterate over all headers
for (let [key, value] of response.headers) {
alert(`${key} = ${value}`);
}
En-ttes de requtes
Pour dfinir un en-tte de requte dans fetch, nous pouvons utiliser loption headers. Il a un objet avec des en-ttes sortants, comme ceci :
let response = fetch(protectedUrl, {
headers: {
Authentication: 'secret'
}
});
Mais il y a une liste den-ttes HTTP interdits que nous ne pouvons pas dfinir :
Accept-Charset,Accept-EncodingAccess-Control-Request-HeadersAccess-Control-Request-MethodConnectionContent-LengthCookie,Cookie2DateDNTExpectHostKeep-AliveOriginRefererTETrailerTransfer-EncodingUpgradeViaProxy-*Sec-*
Ces en-ttes assurent un HTTP correct et sr, ils sont donc contrls exclusivement par le navigateur.
Requtes POST
Pour faire une requte POST, ou une requte avec une autre mthode, nous devons utiliser les options fetch :
methodHTTP-method, par exemplePOST,bodyle corps de la requte, un parmi ceux-ci :- une chane de caractres (par exemple encod en JSON),
- un objet
FormData, pour soumettre les donnes en tant quemultipart/form-data, Blob/BufferSourcepour envoyer des donnes binaires,- URLSearchParams, pour soumettre les donnes au format
x-www-form-urlencoded, rarement utilis.
Le format JSON est utilis la plupart du temps.
Par exemple, ce code soumet lobjet user en JSON :
let user = {
name: 'John',
surname: 'Smith'
};
let response = await fetch('/article/fetch/post/user', {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify(user)
});
let result = await response.json();
alert(result.message);
Veuillez noter que si la requte body est une chane de caractres, alors len-tte Content-Type est dfini sur text/plain;charset=UTF-8 par dfaut.
Mais, si nous envoyons du JSON, nous utiliserons la place loption headers pour envoyer application/json, le bon Content-Type pour les donnes encodes en JSON.
Envoi dune image
Nous pouvons galement soumettre des donnes binaires avec fetch en utilisant des objets Blob ou BufferSource.
Dans cet exemple, il y a un <canvas> o nous pouvons dessiner en dplaant une souris dessus. Un clic sur le bouton submit envoie limage au serveur :
<body style="margin:0">
<canvas id="canvasElem" width="100" height="80" style="border:1px solid"></canvas>
<input type="button" value="Submit" onclick="submit()">
<script>
canvasElem.onmousemove = function(e) {
let ctx = canvasElem.getContext('2d');
ctx.lineTo(e.clientX, e.clientY);
ctx.stroke();
};
async function submit() {
let blob = await new Promise(resolve => canvasElem.toBlob(resolve, 'image/png'));
let response = await fetch('/article/fetch/post/image', {
method: 'POST',
body: blob
});
// le serveur rpond avec confirmation et la taille de l'image
let result = await response.json();
alert(result.message);
}
</script>
</body>
Veuillez noter quici, nous ne dfinissons pas len-tte Content-Type manuellement, car un objet Blob a un type intgr (ici image/png, tel que gnr par toBlob). Pour les objets Blob, ce type devient la valeur de Content-Type.
La fonction submit() peut tre rcrite sans async/await comme ceci :
function submit() {
canvasElem.toBlob(function(blob) {
fetch('/article/fetch/post/image', {
method: 'POST',
body: blob
})
.then(response => response.json())
.then(result => alert(JSON.stringify(result, null, 2)))
}, 'image/png');
}
Rsum
Une requte fetch typique se compose de deux appels await :
let response = await fetch(url, options); // se rsout avec des en-ttes de rponse
let result = await response.json(); // lit le corps en tant que JSON
Ou, sans await :
fetch(url, options)
.then(response => response.json())
.then(result => /* process result */)
Proprits de rponse :
response.statusCode HTTP de la rponse,response.oktrueest le statut 200-299.response.headersobjet Map-like avec en-ttes HTTP.
Mthodes pour obtenir le corps de rponse :
response.text()retourne la rponse sous forme de texte,response.json()analyse la rponse en tant quobjet JSON,response.formData()retourne la rponse en tant quobjetFormData(encodagemultipart/form-data, voir le chapitre suivant),response.blob()retourne la rponse en tant que Blob (donnes binaires avec type),response.arrayBuffer()retourne la rponse en tant que ArrayBuffer (donnes binaires de bas niveau),
Options de fetch jusque l :
methodMthode HTTP,headersun objet avec en-ttes de requte (aucun en-tte nest autoris),bodyles donnes envoyer (corps de la demande) en tant questring,FormData,BufferSource,Blobou objetUrlSearchParams.
Dans les chapitres suivants, nous verrons plus doptions et de cas dutilisation de fetch.
Commentaires
<code>, pour plusieurs lignes enveloppez-les avec la balise<pre>, pour plus de 10 lignes - utilisez une sandbox (plnkr, jsbin, codepen)