fetch() en JavaScript : appeler une API sans recharger la page

fetch() envoie une requête HTTP et rend une promesse. Le piège tient en une ligne : une réponse 404 est un succès, seul le test sur ok le dit.
3 min de lecture
Believemy logo

Charger des données sans recharger la page est devenu la base de toute interface moderne. Pendant longtemps, cela passait par un objet vieillissant aux réglages obscurs. Une fonction unique l'a remplacé.

Elle tient en un appel, mais elle cache un piège qui surprend tout le monde une fois : une réponse en erreur n'est pas une erreur pour elle.


Définition

fetch() envoie une requête HTTP et rend une Promise qui se règle avec un objet Response. Cet objet porte le code de statut et les en-têtes, mais pas encore le corps : le lire demande un second temps d'attente.

JAVASCRIPT
async function chargerProfil(id) {
  const reponse = await fetch("/api/profils/" + id);

  if (!reponse.ok) {
    throw new Error("Statut " + reponse.status);
  }

  return await reponse.json();   // deuxième attente : le corps
}

La propriété ok vaut vrai pour un statut compris entre 200 et 299. Le corps se lit avec json(), text(), blob() ou formData(), selon ce que le serveur a renvoyé.


Ce que fetch appelle une erreur

Le tableau ci-dessous distingue, sur deux colonnes, les situations qui rompent la promesse de celles qui la tiennent malgré une réponse décevante.

SituationComportement de la promesse
Réponse 404 ou 500Tenue, avec ok à faux
Redirection suivieTenue, sur la réponse finale
Serveur injoignableRompue, avec une TypeError
Requête refusée par le navigateurRompue, sans détail lisible
Requête annuléeRompue, avec le nom AbortError

La première ligne est le piège : un catch posé autour d'un appel n'attrapera jamais un 404. Le test sur ok n'est pas facultatif.


Envoyer des données

Une écriture demande trois réglages : la méthode, l'en-tête qui annonce le format, et le corps sérialisé.

JAVASCRIPT
const reponse = await fetch("/api/factures", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ montant: 49, devise: "EUR" }),
  signal: AbortSignal.timeout(8000),
});

Le corps doit être une chaîne, ce que produit JSON avec stringify. Passer directement l'objet enverrait la chaîne [object Object], une erreur silencieuse et difficile à voir.

Bon à savoir

fetch n'abandonne pas tout seul au bout d'un certain temps. Un délai maximal se pose avec un signal, produit par AbortSignal.timeout() ou par un AbortController quand l'annulation doit venir de l'interface.


Questions fréquentes

Question

Pourquoi mon corps de réponse est-il vide au deuxième appel ?

Parce que le corps d'une réponse est un flux, et qu'un flux ne se lit qu'une fois. Un second json() sur le même objet lève une erreur. Si deux parties du code ont besoin du contenu, rangez le résultat dans une variable, ou dupliquez la réponse avec clone() avant la première lecture.


Question

Les cookies partent-ils avec la requête ?

Vers la même origine, oui. Vers un autre domaine, non, sauf si l'option credentials est réglée sur include, et le serveur doit alors l'autoriser explicitement. C'est le point de friction le plus courant entre une interface et une API hébergée ailleurs, décrit en détail par le CORS.


Question

Faut-il encore une bibliothèque pour appeler une API ?

Plus vraiment pour un besoin simple : la fonction est disponible dans tous les navigateurs actuels et dans Node.js sans rien installer. Une bibliothèque garde son intérêt pour les intercepteurs, les nouvelles tentatives automatiques ou la progression d'un envoi. Ce choix, et la couche de gestion d'erreurs qui va avec, se travaille dans la formation JavaScript.

Termes connexes

Découvrez notre glossaire JavaScript

Tous les mots de JavaScript expliqués simplement : mots-clés, objets natifs, méthodes, erreurs et concepts. Définitions claires et exemples qui tournent, pour apprendre et pour se dépanner.

Partager cet article

Tu veux nous aider ? Fais un lien vers cet article sur tes réseaux ou encore mieux : sur ton site, dans un article ou dans ta newsletter.