Cesser d'utiliser XMLHttpRequest et passer à fetch
L’API XHR la plus populaire est XMLHttpRequest
qui n’a pas vraiment été faite pour ce pour quoi nous l’utilisons. C’est pourquoi l’API fetch
a été créée, l’API fetch
est en quelque sorte un remplacement moderne pour XMLHttpRequest
. Jetons un coup d’oeil à cette méthode window.fetch
.
Compatibilité des navigateurs
Une chose importante lors du développement d’une application web est la compatibilité du navigateur avec les technologies utilisées. Comme XMLHttpRequest
est plus ancien, il a logiquement une meilleure compatibilité avec les navigateurs plus anciens par rapport à fetch
, cependant, il y a des polyfill’s bien faits qui rendent cette API moderne compatible avec les navigateurs plus anciens tels que IE, etc…
(c.f Compatibilité XMLHttpRequest, Compatibilité Fetch)
Utilisation de base de XMLHttpRequest
XHR est un peu trop compliqué à mon avis et je ne comprends toujours pas pourquoi XML
est en majuscules alors que Http
est en camel-case, cela n’a aucun sens. Quoi qu’il en soit, voici un usage courant de l’API XHR
if (window.XMLHttpRequest) { // Mozilla, Safari, etc...
request = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
try {
request = new ActiveXObject('Msxml2.XMLHTTP');
}
catch (e) {
try {
request = new ActiveXObject('Microsoft.XMLHTTP');
}
catch (e) {}
}
}
// Ouvre la demande et l'envoie
request.open('GET', 'https://exemple.com/api', true);
request.send(null);
Bien sûr, les frameworks JavaScript rendent l’API XHR plus agréable à utiliser, mais ce que vous voyez ci-dessus est un exemple “simple” de l’utilisation la plus basique de XHR. XHR est un vrai gâchis.
Utilisation de base de fetch
L’API fetch
est fournie dans l’objet window
globale, le premier argument étant l’URL (obligatoire) et le second les options (facultatif).
// fetch(url, options) | url: obligatoire - options: facultatif
fetch('https://exemple.com/api', {
method: 'get'
}).then(function(response) {
// Succès :)
}).catch(function(err) {
// Erreur :(
});
Et comme vous pouvez le voir, fetch
utilise les promesses Javascript pour gérer les résultats et les callbacks. Si vous n’êtes pas encore habitué aux promesses Javascript, habituez-vous - elles seront bientôt partout.
En-têtes de requête
La possibilité de définir des en-têtes de requête est importante dans la flexibilité de la requête, vous pouvez travailler avec les en-têtes de requête en exécutant new Headers()
// Créer une instance d'en-têtes vide
const headers = new Headers();
// Ajouter des en-têtes
headers.append('EnTeteCustom', 'MaSuperValeur');
headers.append('Content-Type', 'text/html');
// Vérifier si cet en-tête est présent
headers.has('Content-Type'); // vrai
headers.has('Some-Header'); // faux
// Obtenir la valeur d'un en-tête spécifique
headers.get('EnTeteCustom'); // MaSuperValeur
// Définir une nouvelle valeur pour un en-tête existant
headers.set('Content-Type', 'text/plain');
// Supprimer une en-tête
headers.delete('EnTeteCustom');
// Additionner les valeurs initiales
const headers = new Headers({
'Content-Type': 'application/json',
'User-Agent': 'MonSuperUserAgent'
});
Pour utiliser les en-têtes de Request, vous devez d’abord créer une nouvelle instance de Request
const request = new Request('https://exemple.com/api', {
headers: new Headers({
'Content-Type': 'application/json',
'User-Agent': 'MonSuperUserAgent'
})
});
fetch(request).then(function(response) {
// traiter la réponse
}).catch(function(error) {
// traiter l'erreur
});
Requête
Une instance de Request
représente l’élément de requête d’un appel de la méthode fetch
. En passant une Request
à l’API fetch, vous pouvez faire des demandes avancées et personnalisées:
method
- GET, HEAD, POST, PUT, DELETEurl
- URL de la requêteheaders
- objet Headers associéreferrer
- référant de la requêtemode
- cors, no-cors, same-origincredentials
- les cookies doivent-ils accompagner la demande ? omit, same-originredirect
- follow, error, manualintegrity
- valeur d’intégrité des sous-ressourcescache
- mode du cache (default, reload, no-cache)
Voici un exemple d’utilisation de Request
// Construire la requête
const request = new Request('https://exemple.com/anything', {
method: 'HEAD',
mode: 'no-cors',
redirect: 'follow',
headers: new Headers({
'Content-Type': 'text/html'
})
});
// Et maintenant, utilisez la requête
fetch(request).then(function() {
// handle response
});
Seul le premier paramètre, l’URL, est requis. Chaque propriété ne peut être que lu dès que l’instance de la Request
a été créée. Il est également important de noter que Request
a une méthode de clonage qui est importante lors de l’utilisation de fetch
dans l’API Service Worker - une Request
est un flux et doit donc être clonée lors du passage à un autre appel de fetch
.
fetch('https://exemple.com/anything', {
method: 'HEAD',
mode: 'no-cors',
redirect: 'follow',
headers: new Headers({
'Content-Type': 'text/html'
})
}).then(function() {
// gérer la réponse
});
Vous n’utiliserez probablement que des instances de Request au sein de Service Workers puisque les signatures Request et fetch peuvent être les mêmes.
Réponse
La méthode then de fetch est une instance de réponse mais vous pouvez également créer manuellement des objets de réponse vous-même – une autre situation que vous pouvez rencontrer lorsque vous utilisez des service workers. Avec une réponse, vous pouvez configurer:
type
- basic, corsurl
useFinalURL
- Booléen pour si url est l’URL finale.status
- code de statut (ex: 200, 404, etc.)ok
- Booléen pour une réponse réussie (statut dans la plage 200-299)statusText
- code de statut (ex: OK)headers
- Objet d’en-tête associé à la réponse.
// Fausse réponse pour les tests des service workers -- new Response(body, options)
const response = new Response('response body', {
ok: false,
status: 404,
url: '/'
});
// Le then de fetch récupère alors une instance de réponse.
fetch('https://exemple.com/').then(function(response) {
console.log('ok: ', response.ok); // faux
});
La Response
fournit également les méthodes suivantes :
clone()
Crée un clone d’un objet Responseerror()
Retourne un nouvel objet Response associé à une erreur réseauredirect()
Crée une nouvelle réponse avec une URL différentearrayBuffer()
Retourne une promesse qui se résout avec un ArrayBufferblob()
Retourne une promesse qui se résout avec un BlobformData()
Retourne une promesse qui se résout avec un objet FormDatajson()
Retourne une promesse qui se résout avec un objet JSONtext()
Retourne une promesse qui se résout avec une USVString (texte)
Manipulation du JSON
Disons que vous faites une requête pour JSON, les données de rappel résultantes ont une méthode json pour convertir les données brutes en objet JavaScript
fetch('https://exemple.com/api/list.json').then(function(response) {
// Convertir en JSON
return response.json();
}).then(function(jsObj) {
// jsObj est un objet javascript de la réponse json
console.log(jsObj);
});
La méthode json()
est un simple raccourci vers JSON.parse(jsonString)
Manipulation des réponses Text/HTML
JSON n’est pas toujours le format de réponse désiré, alors voici comment vous pouvez travailler avec une réponse HTML ou textuelle
fetch('/404').then(function(response) {
return response.text();
}).then(function(htmlresponse) {
// <!DOCTYPE ....
console.log(htmlresponse);
});
Vous pouvez obtenir le texte de réponse enchaînant la méthode then
de la promesse avec la méthode text()
Manipulation des réponses Blob
Par exemple, charger une image via fetch est un peu différent
fetch('https://exemple.com/someimage.jpg').then(function(response) {
return response.blob();
})
.then(function(imageBlob) {
document.querySelector('img').src = URL.createObjectURL(imageBlob);
});
La méthode blob()
du Body mixing prend un flux de réponse et le lit jusqu’à la fin.
Envoyer des données de formulaire
AJAX est beaucoup utilisé pour envoyer des données de formulaire, voici comment vous le feriez avec l’utilisation de fetch
fetch('https://exemple.com/submit', {
method: 'post',
body: new FormData(document.getElementById('myForm'))
});
Et si vous voulez poster des données JSON
fetch('https://exemple.com/submit', {
method: 'post',
body: JSON.stringify({
some: document.querySelector('#some').value,
json: document.querySelector('#json').value,
data: document.querySelector('#data').value
})
});
C’est aussi simple que ça !
Polyfill
Il y a beaucoup de Polyfill pour la méthode fetch, mais je vous suggère fortement de vous pencher sur celle de GitHub.