Fetch API Javascript : Comment l'Utiliser avec des Exemples Simples
Blog, Développement, Tutoriels

Fetch API Javascript : Comment l’Utiliser avec des Exemples Simples

Vous avez besoin d’aller chercher des données sur un serveur en JavaScript ? Vous voulez envoyer des informations depuis votre page web sans la recharger ? Vous trouvez que l’ancien XMLHttpRequest est trop compliqué ?

L’API Fetch est la solution moderne pour gérer les requêtes HTTP en JavaScript natif. Elle est plus simple et plus puissante que les anciennes méthodes. Ce guide vous montre exactement comment l’utiliser avec des exemples de code que vous pouvez copier-coller directement.

Qu’est-ce que l’API Fetch et pourquoi l’utiliser ?

Pour faire simple, l’API Fetch est une fonction intégrée aux navigateurs modernes qui permet à votre code JavaScript de communiquer avec des serveurs. C’est le standard actuel pour faire ce qu’on appelle des requêtes réseau asynchrones. « Asynchrone » veut simplement dire que votre page n’est pas bloquée pendant qu’elle attend la réponse du serveur. L’utilisateur peut continuer à interagir avec le site.

Fetch fonctionne avec un système de Promesses (`Promise`). Une promesse, c’est comme un ticket de vestiaire : vous donnez votre requête et vous recevez une promesse de réponse. Le code continue de s’exécuter, et quand la réponse arrive, la promesse est « tenue » et vous pouvez récupérer vos données. C’est beaucoup plus propre que les anciens systèmes de callbacks.

Voici les principaux avantages de Fetch par rapport à l’ancien XMLHttpRequest :

  • Syntaxe plus simple : Le code est plus court et plus facile à lire.
  • Basé sur les Promesses : Permet d’éviter l’enfer des callbacks (« callback hell ») et de chaîner les opérations de manière logique avec .then() ou async/await.
  • API moderne : Mieux intégrée avec les autres fonctionnalités récentes du web.
  • Plus flexible : La gestion des en-têtes (headers) et des données est plus directe.

En résumé, si vous démarrez un nouveau projet, il n’y a plus de raison d’utiliser XMLHttpRequest. Fetch est la voie à suivre. Le concept central à comprendre est celui d’une une `Promise` (promesse), qui représente une valeur qui sera disponible dans le futur.

Votre première requête : Récupérer des données avec GET

La requête la plus courante est la requête GET. Elle sert à récupérer des informations d’un serveur. Avec Fetch, c’est très simple. La fonction de base est fetch(url). Elle prend en paramètre l’URL de la ressource que vous voulez récupérer.

Par défaut, fetch() effectue toujours une requête GET, donc vous n’avez rien de plus à préciser. Comme fetch() retourne une promesse, vous devez « chaîner » des méthodes .then() pour traiter la réponse quand elle arrive.

Avec la syntaxe .then()

C’est l’approche classique avec les promesses. Le premier .then() reçoit la réponse globale du serveur. Mais attention, ce n’est pas encore vos données ! Vous devez utiliser une méthode comme .json() pour extraire les données au format JSON. Cette méthode retourne elle-même une nouvelle promesse, d’où le deuxième .then().

// URL d'une API de test qui renvoie des données utilisateur
const url = 'https://jsonplaceholder.typicode.com/users/1';

fetch(url)
  .then(response => {
    // On vérifie si la requête a réussi (status code dans les 200)
    if (!response.ok) {
      throw new Error('La requête a échoué');
    }
    // On transforme la réponse en JSON
    return response.json(); 
  })
  .then(data => {
    // Ici, 'data' contient l'objet JSON final
    console.log(data); 
  })
  .catch(error => {
    // S'il y a eu une erreur réseau ou dans le traitement
    console.error('Erreur attrapée:', error);
  });

Avec la syntaxe async/await

C’est une manière plus moderne et souvent plus lisible d’écrire du code asynchrone. Elle permet d’écrire le code comme s’il était synchrone (ligne par ligne), ce qui le rend plus facile à suivre. Pour l’utiliser, votre code doit être dans une fonction déclarée avec le mot-clé async.

Le mot-clé await met en pause l’exécution de la fonction jusqu’à ce que la promesse soit résolue. On utilise un bloc try...catch pour gérer les erreurs, ce qui est une pratique courante en JavaScript.

const url = 'https://jsonplaceholder.typicode.com/users/1';

// La fonction doit être déclarée "async" pour pouvoir utiliser "await"
async function getUser() {
  try {
    const response = await fetch(url);

    if (!response.ok) {
      throw new Error(`Erreur HTTP: ${response.status}`);
    }

    // Await attend que la conversion en JSON soit terminée
    const data = await response.json();
    console.log(data);

  } catch (error) {
    console.error('Impossible de récupérer l\'utilisateur:', error);
  }
}

// On appelle la fonction pour l'exécuter
getUser();

Envoyer des données au serveur avec POST

Pour créer ou modifier des données sur un serveur, on utilise généralement une requête POST. Contrairement à GET, une requête POST doit contenir les données à envoyer. Avec Fetch, cela se fait en passant un deuxième argument à la fonction : un objet d’options de configuration.

Cet objet doit contenir au minimum trois propriétés :

  • method : La méthode HTTP à utiliser, ici 'POST'.
  • headers : Des informations sur la requête. Pour envoyer du JSON, il faut absolument préciser 'Content-Type': 'application/json' pour que le serveur sache comment interpréter les données.
  • body : Le contenu de la requête. Si vous envoyez un objet JavaScript, vous devez le transformer en chaîne de caractères JSON avec JSON.stringify().

Voici un exemple complet pour envoyer un nouvel article de blog à une API.

const url = 'https://jsonplaceholder.typicode.com/posts';

// Les données que nous voulons envoyer
const newPost = {
  title: 'Mon super article',
  body: 'Contenu de l\'article...',
  userId: 1,
};

// L'objet d'options pour la requête fetch
const fetchOptions = {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(newPost), // On convertit l'objet JS en chaîne JSON
};

// On exécute la requête
fetch(url, fetchOptions)
  .then(response => {
    if (!response.ok) {
      throw new Error('La requête POST a échoué');
    }
    return response.json(); // Le serveur renvoie souvent les données créées
  })
  .then(createdPost => {
    console.log('Article créé avec succès:', createdPost);
  })
  .catch(error => {
    console.error('Erreur lors de la création:', error);
  });

Gérer la réponse : L’objet Response

Un point très important à comprendre est que la promesse de fetch() ne vous donne pas directement les données (le JSON, le texte, etc.). Elle se résout avec un objet Response. Cet objet est une représentation de toute la réponse HTTP envoyée par le serveur.

Cet l’objet `Response` contient des informations comme le statut de la réponse, les en-têtes, et surtout, des méthodes pour lire le corps (body) de la réponse. Le corps de la réponse ne peut être lu qu’une seule fois.

Voici les méthodes les plus utiles pour lire le corps de la réponse :

  • .json() : Tente de parser le corps comme du JSON.
  • .text() : Lit le corps comme du texte brut.
  • .blob() : Traite le corps comme un fichier binaire (utile pour les images, PDF, etc.).
  • .formData() : Lit le corps comme des données de formulaire.
  • .arrayBuffer() : Traite le corps comme un ArrayBuffer (données binaires brutes).
Vérifiez toujours le statut de la réponse

L’objet Response a une propriété très pratique : response.ok. C’est un booléen (true/false) qui est à true si le code de statut HTTP est un succès (entre 200 et 299). Vous avez aussi accès au code exact avec response.status (ex: 200, 404, 500).

async function checkStatus() {
  const response = await fetch('https://jsonplaceholder.typicode.com/posts/9999'); // Cette ressource n'existe pas

  console.log(`Status OK: ${response.ok}`); // Affiche: false
  console.log(`Status Code: ${response.status}`); // Affiche: 404
}

checkStatus();

Tableau des options de configuration (`init`)

Pour personnaliser vos requêtes, vous passez un objet d’options (souvent appelé init) comme second argument à fetch(). Nous avons vu method, headers et body, mais il en existe beaucoup d’autres pour un contrôle plus fin.

Ce tableau récapitulatif présente les options de configuration les plus courantes. Chaque option vous permet de personnaliser le comportement de votre requête. La plupart de ces options sont définies sur l’interface `Request` et les en-têtes sur l’interface `Headers`.

Option Description Exemples de valeurs
method La méthode de requête HTTP. 'GET', 'POST', 'PUT', 'DELETE', 'PATCH'. La valeur par défaut est 'GET'.
headers Les en-têtes de la requête (objet ou instance de Headers). { 'Content-Type': 'application/json', 'Authorization': 'Bearer ...' }
body Le corps de la requête. Doit être une chaîne de caractères, un Blob, un FormData, etc. JSON.stringify({ key: 'value' })
mode Le mode de la requête, qui affecte les requêtes cross-origin (entre domaines différents). 'cors' (défaut), 'no-cors', 'same-origin'.
cache Indique comment la requête interagit avec le cache du navigateur. 'default', 'no-store', 'reload', 'no-cache'.
credentials Définit si le navigateur doit envoyer les cookies et les en-têtes d’authentification. 'include' (envoyer), 'same-origin' (défaut), 'omit' (ne pas envoyer).
signal Un objet AbortSignal pour pouvoir annuler la requête. controller.signal (voir la section sur l’annulation).
redirect Comment gérer les redirections. 'follow' (défaut), 'manual', 'error'.

La gestion des erreurs avec Fetch

C’est un point absolument crucial et une source d’erreur fréquente pour les débutants. Contrairement à beaucoup d’autres librairies, fetch() ne rejette pas sa promesse pour les erreurs HTTP. Cela veut dire qu’une réponse avec un statut 404 (Not Found) ou 500 (Internal Server Error) ne déclenchera PAS le bloc .catch() !

Le .catch() n’est déclenché que pour les erreurs réseau, par exemple si l’utilisateur est déconnecté d’Internet ou si le serveur est inaccessible.

La règle d’or de la gestion d’erreur

Vous devez TOUJOURS vérifier manuellement le statut de la réponse avec la propriété response.ok. Si elle est à false, c’est à vous de lancer une erreur pour qu’elle soit attrapée par le bloc catch.

Voici le pattern correct à utiliser, surtout avec async/await :

async function getData(url) {
  try {
    const response = await fetch(url);

    // C'est LA ligne la plus importante pour la gestion des erreurs
    if (!response.ok) {
      // On crée et on lance une nouvelle erreur qui sera attrapée par le catch
      throw new Error(`Erreur HTTP ! Statut: ${response.status}`);
    }

    const data = await response.json();
    console.log('Données reçues :', data);

  } catch (error) {
    // Ce bloc attrape les erreurs réseau ET les erreurs que nous avons lancées
    console.error('Une erreur est survenue :', error);
  }
}

// Test avec une URL qui n'existe pas
getData('https://api.github.com/users/unutilisateurquinexistepas12345');

En suivant ce modèle, vous séparez bien la logique de succès de la logique d’erreur et votre code sera beaucoup plus robuste.

Annuler une requête Fetch (Avancé)

Il peut être utile d’annuler une requête en cours. Par exemple, si l’utilisateur change de page ou clique sur un bouton « Annuler » pendant un long chargement. Pour cela, on utilise une autre API du navigateur : AbortController.

Le fonctionnement est simple :

  1. On crée une instance de AbortController.
  2. On passe son AbortSignal (controller.signal) dans les options de la requête Fetch.
  3. Pour annuler, on appelle la méthode controller.abort().

L’annulation de la requête provoquera le rejet de la promesse de Fetch, qui sera attrapée par le bloc catch.

// 1. On crée le contrôleur
const controller = new AbortController();
const signal = controller.signal;

const url = 'https://jsonplaceholder.typicode.com/todos';

// 2. On passe le signal dans les options
fetch(url, { signal })
  .then(response => response.json())
  .then(data => console.log('Données reçues', data))
  .catch(err => {
    if (err.name === 'AbortError') {
      console.log('Requête annulée !');
    } else {
      console.error('Autre erreur', err);
    }
  });

// 3. On annule la requête après 50 millisecondes (par exemple)
setTimeout(() => controller.abort(), 50);

L’objet `AbortController` est l’outil standard pour ce type de tâche.

FAQ – Questions fréquentes sur l’API Fetch

Voici les réponses aux questions les plus courantes sur l’API Fetch.

Quelle est la différence entre Fetch et Axios ?

Fetch et Axios servent tous les deux à faire des requêtes HTTP. La principale différence est que Fetch est natif au navigateur (pas besoin d’installer de librairie), alors qu’Axios est une librairie externe. Axios offre des fonctionnalités pratiques par défaut que Fetch n’a pas, comme :

  • Transformation automatique des données en JSON.
  • Gestion des erreurs HTTP (un 404 rejette la promesse).
  • Protection contre les attaques XSRF.
  • Intercepteurs de requêtes et de réponses.
  • Gestion des timeouts et de l’annulation plus simple.

Conclusion : Pour des besoins simples, Fetch est parfait. Pour de grosses applications avec des besoins complexes, Axios peut vous faire gagner du temps.

Comment gérer les problèmes de CORS avec Fetch ?

CORS (Cross-Origin Resource Sharing) est une sécurité gérée par le serveur, pas par votre code JavaScript. Si vous faites une requête vers un autre domaine et que vous obtenez une erreur CORS, c’est que le serveur n’autorise pas votre domaine à accéder à ses ressources. Vous ne pouvez rien y faire côté client, sauf si l’API le permet.

L’option mode: 'no-cors' dans Fetch peut sembler une solution, mais elle est très limitée. Elle vous permet d’envoyer une requête « opaque » mais vous ne pourrez pas lire la réponse. Elle sert à des cas très spécifiques comme l’envoi de logs ou le préchargement de cache.

Fetch est-il compatible avec tous les navigateurs ?

Oui, Fetch est compatible avec tous les navigateurs modernes, y compris Chrome, Firefox, Safari, et Edge. Le seul navigateur majeur qui ne le supporte pas est Internet Explorer. Si vous devez absolument supporter IE, vous devrez utiliser un « polyfill » (un morceau de code qui ajoute la fonctionnalité) ou vous en tenir à XMLHttpRequest.

Vous pourriez également aimer...