L'API Fetch s'est imposée comme le successeur naturel d'XMLHttpRequest (XHR) pour l'exécution des requêtes HTTP en JavaScript. Intégrée nativement dans tous les navigateurs modernes et Node.js 18+, elle capitalise sur les Promesses pour offrir une interface élégante, puissante et facile à utiliser. Oubliez jQuery.ajax() ou même Axios pour vos besoins de base ; Fetch pourrait bien être tout ce dont vous avez besoin.

Requête GET Basique

Requête GET
// Requête GET simple
const response = await fetch('https://api.example.com/users');
const users = await response.json();
console.log(users);

// Avec gestion d'erreurs
async function getUsers() {
  const response = await fetch('https://api.example.com/users');

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

  return response.json();
}

Point essentiel : La fonction fetch() ne rejettera une promesse qu'en cas d'erreur réseau (serveur inaccessible, problème de CORS). Les codes de statut HTTP indiquant une erreur côté client (404, 403) ou serveur (500, 503) sont traités comme des réponses réussies. Il est donc primordial de toujours vérifier manuellement la propriété response.ok.

Requêtes POST, PUT, DELETE

POST — Créer une Ressource
const response = await fetch('https://api.example.com/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer eyJhbGci...',
  },
  body: JSON.stringify({
    name: 'Alice',
    email: '[email protected]',
  }),
});

const newUser = await response.json();
PUT — Mettre à Jour une Ressource
await fetch('https://api.example.com/users/123', {
  method: 'PUT',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: 'Alice Updated' }),
});
DELETE — Supprimer une Ressource
await fetch('https://api.example.com/users/123', {
  method: 'DELETE',
  headers: { 'Authorization': 'Bearer token123' },
});

Types de Réponses

Analyse des Différents Types de Réponses
const response = await fetch(url);

// JSON
const data = await response.json();

// Texte brut
const text = await response.text();

// Données binaires (images, fichiers)
const blob = await response.blob();

// ArrayBuffer (binaire pur)
const buffer = await response.arrayBuffer();

// Données de formulaire
const formData = await response.formData();

// Métadonnées de la réponse
console.log(response.status);      // 200
console.log(response.statusText);  // "OK"
console.log(response.ok);          // true (200-299)
console.log(response.headers.get('Content-Type'));

AbortController — Annuler les Requêtes

Annuler une Requête Fetch
const controller = new AbortController();

// Annuler après 5 secondes
const timeoutId = setTimeout(() => controller.abort(), 5000);

try {
  const response = await fetch('https://api.example.com/data', {
    signal: controller.signal,
  });
  clearTimeout(timeoutId);
  const data = await response.json();
} catch (err) {
  if (err.name === 'AbortError') {
    console.log('Requête annulée pour dépassement de délai');
  } else {
    throw err;
  }
}

Téléchargement de Fichiers

Télécharger avec FormData
const formData = new FormData();
formData.append('avatar', fileInput.files[0]);
formData.append('name', 'Alice');

// Ne définissez pas Content-Type — le navigateur le gère automatiquement avec la délimitation
const response = await fetch('/api/upload', {
  method: 'POST',
  body: formData,
});

Client API Fetch Réutilisable

Client API
class ApiClient {
  constructor(baseUrl, token) {
    this.baseUrl = baseUrl;
    this.token = token;
  }

  async request(path, options = {}) {
    const response = await fetch(`${this.baseUrl}${path}`, {
      ...options,
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${this.token}`,
        ...options.headers,
      },
    });

    if (!response.ok) {
      const error = await response.json().catch(() => ({}));
      throw new Error(error.message || `HTTP ${response.status}`);
    }

    return response.json();
  }

  get(path) { return this.request(path); }
  post(path, data) { return this.request(path, { method: 'POST', body: JSON.stringify(data) }); }
  put(path, data) { return this.request(path, { method: 'PUT', body: JSON.stringify(data) }); }
  delete(path) { return this.request(path, { method: 'DELETE' }); }
}

// Utilisation
const api = new ApiClient('https://api.example.com', 'token123');
const users = await api.get('/users');
const newUser = await api.post('/users', { name: 'Alice' });

Erreurs Courantes à Éviter

  • Omettre de vérifier response.ok : Les codes d'erreur HTTP tels que 404 ou 500 ne provoquent pas le rejet de la promesse Fetch. Il est indispensable de procéder à cette vérification manuellement pour détecter les échecs logiques.
  • Définir manuellement le Content-Type pour FormData : Lorsque vous envoyez des données via FormData, le navigateur gère automatiquement l'en-tête Content-Type avec le paramètre `boundary`. Tenter de le définir vous-même peut entraîner des erreurs.
  • Appeler response.json() (ou .text(), .blob(), etc.) plus d'une fois : Le corps d'une réponse Fetch ne peut être lu et consommé qu'une seule fois. Si vous avez besoin d'accéder aux données plusieurs fois, stockez le résultat de la première lecture dans une variable.
  • Ne pas gérer spécifiquement l'AbortError : Lorsque vous annulez une requête Fetch à l'aide d'un AbortController, la promesse associée sera rejetée avec une erreur dont la propriété name sera `'AbortError'`. Il est conseillé de la gérer distinctement des autres types d'erreurs.

Découvrez Nos Outils Gratuits pour Développeurs

Optimisez la lisibilité de vos réponses d'API et encodez facilement vos paramètres de requête.