Fetch API and HTTP Requests
Fetch API is the new way to make HTTP requests in JavaScript
It replaces XMLHttpRequest (XHR) and uses Promises (XMLHttpRequest was the old way of doing it, we
won't see it here, since it's an 'outdated' method ;) )
We can also use AXIOS ?? -> historically, it was a better way to do it than XMLHttpRequest,
but since the release of fetch, natively in js it is not so true anymore, and in most cases fetch is lighter, native.
and just as effective.
Introduction to Fetch
Basic syntax: fetch(url, options)
fetch() always returns a Promise
Simple GET Request
async function exempleGetSimple() {
try {
// Request to a test API (JSONPlaceholder)
const response = await fetch('https://jsonplaceholder.typicode.com/users/1');
// Check if the request was successful
if (!response.ok) {
throw new Error(`HTTP Error: ${response.status}`);
}
// Convert the response to JSON
const utilisateur = await response.json();
console.log("Utilisateur récupéré:", utilisateur);
return utilisateur;
} catch (erreur) {
console.error("Erreur lors de la requête:", erreur.message);
throw erreur;
}
}
// Calling the function (will only be executed if the API is accessible)
// exempleGetSimple();
HTTP Methods
The main HTTP methods and their usage
GET: Retrieve data
async function obtenirUtilisateurs() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
if (!response.ok) {
throw new Error(`Erreur: ${response.status} ${response.statusText}`);
}
const utilisateurs = await response.json();
console.log(`${utilisateurs.length} utilisateurs récupérés`);
return utilisateurs;
} catch (erreur) {
console.error("Erreur GET:", erreur.message);
return [];
}
}
POST: Create data
async function creerUtilisateur(nouvelUtilisateur) {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(nouvelUtilisateur)
});
if (!response.ok) {
throw new Error(`Erreur: ${response.status}`);
}
const utilisateurCree = await response.json();
console.log("Utilisateur créé:", utilisateurCree);
return utilisateurCree;
} catch (erreur) {
console.error("Erreur POST:", erreur.message);
throw erreur;
}
}
// Example of use
const nouvelUtilisateur = {
name: "Jean Dupont",
email: "jean.dupont@example.com",
phone: "01 23 45 67 89"
};
// creerUtilisateur(nouvelUtilisateur);
PUT: Update completely
async function mettreAJourUtilisateur(id, utilisateur) {
try {
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(utilisateur)
});
const utilisateurMisAJour = await response.json();
console.log("Utilisateur mis à jour:", utilisateurMisAJour);
return utilisateurMisAJour;
} catch (erreur) {
console.error("Erreur PUT:", erreur.message);
throw erreur;
}
}
PATCH: Update partially
async function mettreAJourPartiel(id, modifications) {
try {
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(modifications)
});
const utilisateurModifie = await response.json();
console.log("Utilisateur modifié:", utilisateurModifie);
return utilisateurModifie;
} catch (erreur) {
console.error("Erreur PATCH:", erreur.message);
throw erreur;
}
}
DELETE: Delete data
async function supprimerUtilisateur(id) {
try {
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`, {
method: 'DELETE'
});
if (response.ok) {
console.log(`Utilisateur ${id} supprimé`);
return true;
} else {
throw new Error(`Impossible de supprimer l'utilisateur ${id}`);
}
} catch (erreur) {
console.error("Erreur DELETE:", erreur.message);
return false;
}
}
Header Management
Headers allow you to send metadata with requests
Authentication Headers
async function requeteAvecAuth(token) {
try {
const response = await fetch('https://api.example.com/protected', {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
'Accept': 'application/json'
}
});
return await response.json();
} catch (erreur) {
console.error("Erreur authentification:", erreur.message);
throw erreur;
}
}
Custom Headers
async function requeteAvecHeadersCustom() {
const headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('X-API-Key', 'ma-clé-secrète');
headers.append('User-Agent', 'MonApp/1.0');
try {
const response = await fetch('https://api.example.com/data', {
method: 'GET',
headers: headers
});
return await response.json();
} catch (erreur) {
console.error("Erreur headers custom:", erreur.message);
throw erreur;
}
}
Checking the response status
async function verifierStatutReponse(url) {
try {
const response = await fetch(url);
console.log("Statut:", response.status);
console.log("Statut texte:", response.statusText);
console.log("URL finale:", response.url);
console.log("Redirected:", response.redirected);
// Different status codes
if (response.status >= 200 && response.status < 300) {
console.log("Succès");
} else if (response.status >= 300 && response.status < 400) {
console.log("Redirection");
} else if (response.status >= 400 && response.status < 500) {
console.log("Erreur client");
} else if (response.status >= 500) {
console.log("Erreur serveur");
}
return response;
} catch (erreur) {
console.error("Erreur réseau:", erreur.message);
throw erreur;
}
}
Timeout and cancellation
Timeout with AbortController
async function requeteAvecTimeout(url, timeoutMs = 5000) {
// Create an AbortController to cancel the request
const controller = new AbortController();
// Schedule the cancellation after the timeout
const timeoutId = setTimeout(() => {
controller.abort();
}, timeoutMs);
try {
const response = await fetch(url, {
signal: controller.signal
});
// Cancel the timeout if the request succeeds
clearTimeout(timeoutId);
return await response.json();
} catch (erreur) {
clearTimeout(timeoutId);
if (erreur.name === 'AbortError') {
throw new Error(`Timeout après ${timeoutMs}ms`);
}
throw erreur;
}
}
Manual cancellation
let controllerGlobal = null;
function demarrerRequeteLongue() {
controllerGlobal = new AbortController();
return fetch('https://httpbin.org/delay/10', {
signal: controllerGlobal.signal
})
.then(response => response.json())
.then(data => console.log("Requête terminée:", data))
.catch(erreur => {
if (erreur.name === 'AbortError') {
console.log("Requête annulée par l'utilisateur");
} else {
console.error("Erreur:", erreur.message);
}
});
}
function annulerRequete() {
if (controllerGlobal) {
controllerGlobal.abort();
console.log("Annulation demandée");
}
}