Fetch vs Axios pour les requêtes HTTP
Ceci est mon tout premier article et je le dédie à une question qui laisse plus d'un développeur perplexe. Quelle est la différence entre Fetch et Axios quand chacun devrait-il être utilisé? Les appels AJAX font partie de notre routine quotidienne depuis un bon moment et lorsque je planifie mon code, Axios me vient aussitôt en tête comme solution évidente. Mais qu'est-ce que Fetch, d'où vient-il et devrions-nous plutôt utiliser ce dernier?
Notez bien, cet article n'est pas une étude approfondie de ces outils et ne traitera pas de leur nature existentielle, de leur raison d'être ni de l'étendue de leur fonctionnalités mais fournira un aperçu de leurs atouts clés ainsi que leur pour+contre.
Premièrement, faisons un petit retour sur ce qu'est Axios. Axios est un "wrapper", un décorateur, un "API / promise-based HTTP client" facile à utiliser. Il offre une interface que plusieurs trouvent agréable à utiliser. C'est une librairie de tierce partie (n'est pas JavaScript Vanille) qui peut être utilisé autant du côté client que serveur. Une importante différence est qu'il n'est pas fourni de manière naturelle par le fureteur pour JavaScript, cet outil doit être installé et importé (dépendance) dans le projet afin d'être disponible. Avant d'opter pour Axios, 2 principaux facteurs sont à considérer. Premièrement, le fait d'ajouter une librairie de tierce partie apporte un poids/charge considérable sur l'application ou le site web et cette charge additionnelle devrait toujours être évalué même si le trafic est faible. Ensuite, il faut aussi garder en tête qu'il ne fait pas partie du standard (natif JavaScript). Une responsabilité s'impose alors pour gérer le risque de conflits potentiels. Mais la bonne nouvelle est que c'est une librairie de tierce partie qui est bien populaire et supportée, même pour IE11!
De l'autre côté, Fetch est une solution plus moderne et simplifiée de son prédécesseur moins apprécié XMLHttpRequest (XHR). Il a été introduit avec ECMAScript 2015 (ES6) et est maintenant supporté par la majorité des fureteurs populaires (à l'exception de Internet Explorer). Fetch facilite les requêtes asynchrones et gère les réponses de manière plus directe que le XMLHttpRequest. Fetch possède l'avantage d'être natif JavaScript et il n'est donc pas nécessaire de l'installer ni de l'importer et on n'a pas à se soucier de conflits potentiels vu qu'il ne provient pas d'une librairie de tierce partie. Fetch résides dans le fureteur et peut alors simplement être utilisé du côté client mais il n'est pas disponible du côté serveur. Les utilisateur de NodeJS ont plusieurs alternatives dont Node-Fetch ou Axios. Plusieurs sources d'information mentionnent que Fetch ne fournit pas de solution comme l'annulation d'une requête ("Cancel Request"), en comparaison avec Axios, mais ceci peut certainement être fait à l'aide de l'arrivée récente du AbortController qui est supporté par la majorité des fureteurs populaires (à l'exception de Internet Explorer).
Voyons quelques différences de syntaxe entre ces deux outils.
Ceci est un appel AJAX simple de type GET avec Axios:
axios.get('https://some-url/api/some-endpoint')
.then(response => console.log(response))
.catch(error => console.log(error.message));
Voici l'équivalent en employant une syntaxe différente avec Fetch:
fetch('https://some-url/api/some-endpoint')
.then(response => {
if (!response.ok) {
throw Error(response.statusText);
}
return response.json();
})
.then(data => console.log(data))
.catch(error => console.log(error));
Comme vous pouvez le constater, lorsqu'on fait ce type d'appel (GET, dans cet exemple) avec Axios, vous spécifiez la méthode HTTP et vous pouvez utiliser la même syntaxe avec les autres méthodes HTTP.
Voici un exemple d'appel de type POST avec Axios ci-dessous:
const postData = { firstName: 'Korben', lastName: 'Dallas' };
const apiURL = 'https://top-movies.com/api/the-fifth-element/character';
axios({
method: 'post',
url: apiURL,
data: postData,
})
.then(response => console.log('Success: ', response))
.catch(error => console.log('Error: ', error));
Ce même appel peut être simplifié ainsi lorsque la configuration n'est pas nécessaire:
const postData = { firstName: 'Korben', lastName: 'Dallas' };
const apiURL = 'https://top-movies.com/api/the-fifth-element/character';
axios.post(apiURL, {
...postData
})
.then(response => console.log('Success: ', response))
.catch(error => console.log('Error: ', error));
Cependant, avec Fetch, il n'est pas nécessaire de spécifier la méthode pour un appel de type GET parce qu'elle est considérée par défaut lorsqu'aucune méthode est spécifiée. Les autres méthodes HTTP doivent être spécifiées dans les options de la requête. Le contenu/data doit être converti au préalable en JSON avant d'être inséré à la propriété body des options de la requête.
Nous avons ci-dessous un exemple d'appel équivalent mais avec la syntaxe différente de Fetch:
const postData = { firstName: 'Korben', lastName: 'Dallas' };
const apiURL = 'https://top-movies.com/api/the-fifth-element/character';
fetch(apiURL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(postData),
})
.then(response => response.json())
.then(jsonResponse => console.log('Success: ', jsonResponse))
.catch(error => console.log('Error: ', error));
En comparaison, lorsque l'appel est fait avec Axios, le contenu/data est acheminé par la propriété data des options de la requête et il n'est pas nécessaire de convertir en JSON au préalable.
Une autre particularité de Fetch est qu'une validation additionnelle doit être effectuée sur la réponse parce que Fetch retourne toujours une réponse, qu'elle soit avec succès ou pas.
Voici un exemple de réponse pour un appel qui de manière intentionnelle n'a pas été effectué avec succès (400 : Bad Request):
C'est la raison pour laquelle j'ai ajouté une validation additionnelle sur la propriété ok de la réponse. Il est à noter que la gestion d'exception n'est pas optimisée dans cet exemple:
fetch('https://some-url/api/some-endpoint')
.then(response => {
if (!response.ok) {
throw Error(response.statusText);
}
return response.json();
})
.then(data => console.log(data))
.catch(error => console.log(error));
Puis, certains développeurs se plaignent qu'Axios offre un support de réponse plus approprié que Fetch au fait qu'il n'est pas nécessaire de convertir le contenu de la réponse afin d'obtenir le format utile JSON. Avec Fetch, il est nécessaire de convertir manuellement (ce qui n'est pas nécessairement un enjeu selon moi):
fetch('https://some-url/api/some-endpoint')
.then(response => {
if (!response.ok) {
throw Error(response.statusText);
}
return response.json();
})
.then(data => console.log(data))
.catch(error => console.log(error));
De plus, il y a beaucoup de publicité négative à l'égard du bon vieux XMLHttpRequest (XHR) mais dans des cas simples, il peut certainement et facilement encore satisfaire les requis. Voyons ci-dessous un exemple simple avec XHR:
// Création de l'instance de l'objet de requête XHR
const xhr = new XMLHttpRequest();
// Initialisation de la requête. Paramètres additionnels à ajouter au besoin
xhr.open('GET', 'https://some-url/api/some-endpoint');
// Différents types de réponse peuvent être spécifiés ('string' par défaut).
xhr.responseType = 'json';
// Envoie de la requête
xhr.send();
// Écoute sur l'événement pour la réponse
xhr.onload = () => {
if (xhr.status != 200) {
// Note: cette gestion d'exception devrait être optimisée
alert('Error: ' + xhr.status);
return;
}
// La réponse est obtenue par la propriété response
console.log('Response: ', xhr.response);
};
Cette méthode est plus laborieuse en effet mais elle reste assez simple et elle est une option à considérer lors de situations appropriées.
Conclusion
Je risque de décevoir le lecteur qui s'attend à une réponse tranchante, absolue et inconditionnelle sur la question "devrais-je utiliser Fetch ou Axios" mais ça ne serait pas juste parce qu'en réalité, comme pour bien des outils et langages de programmation à notre portée, je suis un de ceux qui croient qu'ils ont chacun un but et l'opportunité d'être utiles ou même la solution idéale lorsqu'utilisé de la bonne manière et au bon endroit.
Fetch et Axios comportent chacun des fonctionnalités avantageuses et mise à part le fait que la syntaxe et la simplicité diffère, il est essentiel de garder en tête que la solution la plus plaisante ou excitante pour le développeur n'est peut-être pas la plus efficace ou optimale en terme de performance du produit, et donc de l'expérience utilisateur. Un moment de réflexion est toujours important au moment où l'on choisit l'outil à utiliser.
TL;DR;
Pour ceux qui sont continuellement dans l'action et qui cherchent les raccourcis, voici un résumé des points principaux pour chacun de ces outils:
Axios
POUR:
"API / Promise based HTTP client" disponible dans le fureteur et au niveau du serveur (NodeJS)
Compatible avec certains anciens fureteurs (ex. IE11)
Fournit l'annulation de requête ("Cancel Request") ⇒ qui peut aussi être effectué sans Axios à l'aide du AbortController)
Librairie de tierce partie très populaire activement supportée
"Wrapper" / décorateur qui offre une interface simple et agréable
CONTRE:
Doit être installé et importé (n'est pas natif JavaScript)
N'est pas le standard et il est donc important de gérer les conflits potentiels
Les librairies de tierce partie ajoutent un poids/charge sur l'application ou site web (à considérer)
Fetch
POUR:
Natif dans les fureteurs modernes (pas besoin d'installer ou d'importer)
Standard JavaScript (Vanille)
Solution légère
Solution moderne et agréable qui peut remplacer le moins apprécié XMLHttpRequest (XHR)
CONTRE:
Requière une étape additionnelle de conversion JSON pour la requête et sur la réponse
Requière une gestion de la réponse et des exceptions étant donné que Fetch retourne toujours une réponse (même si l'appel n'est pas un succès)
Pas compatible avec les anciens fureteurs (ex. IE11)
Seulement disponible du côté client (fureteur)
Références
API Fetch
Compatibilité des fureteurs pour Fetch
Documentation et compatibilité des fureteurs pour Axios
Utilisation du AbortController
Compatibilité des fureteurs pour AbortController
Appels XHR
Merci pour votre intérêt!