1. Pourquoi Axios ?
Axios est un client HTTP basé sur les Promises, fonctionnant aussi bien
dans le navigateur que dans Node.js. Il simplifie drastiquement les appels réseau par rapport à l'API
fetch native grùce à plusieurs fonctionnalités intégrées.
fetch natif vs Axios
| Fonctionnalité | fetch natif | Axios |
|---|---|---|
| JSON automatique | Manuel (.json()) | Automatique |
| Erreurs HTTP (4xx, 5xx) | Pas rejetées | Rejets automatiques |
| Intercepteurs | Non natif | Intégrés |
| Annulation | AbortController seul | AbortController + helpers |
| Instances configurées | Non | axios.create() |
| Upload progress | Non natif | onUploadProgress |
| Support IE/vieux browsers | Non | Polyfill inclus |
| Timeout intégré | Non | timeout: ms |
Installation
# Via npm (Node.js / bundler)
npm install axios
# Via CDN (navigateur, sans bundler)
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
Premier appel
// GET de base avec Axios
axios.get('https://jsonplaceholder.typicode.com/users')
.then(response => {
console.log(response.data); // tableau d'utilisateurs
console.log(response.status); // 200
})
.catch(error => {
console.error('Erreur :', error.message);
});
// Avec async/await (recommandé)
async function chargerUtilisateurs() {
try {
const response = await axios.get('https://jsonplaceholder.typicode.com/users');
console.log(response.data); // JSON déjà parsé !
} catch (error) {
console.error('Erreur :', error.message);
}
}
fetch, vous devez toujours appeler .json() pour parser la réponse. Avec Axios,
response.data contient directement l'objet JavaScript parsé.
2. Méthodes HTTP
Axios expose une méthode pour chaque verbe HTTP. Chaque méthode retourne une Promise qui se résout
en un objet response ou se rejette en cas d'erreur réseau ou HTTP.
axios.get(url, config?)
// GET â rĂ©cupĂ©rer des donnĂ©es
const response = await axios.get('https://jsonplaceholder.typicode.com/posts/1');
console.log(response.data); // { id: 1, title: '...', ... }
// GET avec paramĂštres de query (?userId=1&_limit=5)
const res = await axios.get('https://jsonplaceholder.typicode.com/posts', {
params: { userId: 1, _limit: 5 }
});
console.log(res.data); // tableau de 5 posts de l'utilisateur 1
axios.post(url, data, config?)
// POST â crĂ©er une ressource
const nouvelArticle = {
title: 'Mon article',
body: 'Contenu de l\'article',
userId: 1
};
const response = await axios.post(
'https://jsonplaceholder.typicode.com/posts',
nouvelArticle
);
console.log(response.data); // { id: 101, title: '...', ... }
console.log(response.status); // 201 Created
axios.put(url, data, config?)
// PUT â remplacer entiĂšrement une ressource
const articleMisAJour = {
id: 1,
title: 'Titre modifié',
body: 'Nouveau contenu complet',
userId: 1
};
const response = await axios.put(
'https://jsonplaceholder.typicode.com/posts/1',
articleMisAJour
);
console.log(response.data); // { id: 1, title: 'Titre modifié', ... }
axios.patch(url, data, config?)
// PATCH â modifier partiellement une ressource
const response = await axios.patch(
'https://jsonplaceholder.typicode.com/posts/1',
{ title: 'Nouveau titre seulement' } // seul le titre est modifié
);
console.log(response.data);
axios.delete(url, config?)
// DELETE â supprimer une ressource
const response = await axios.delete(
'https://jsonplaceholder.typicode.com/posts/1'
);
console.log(response.status); // 200
// Vérifier la suppression
if (response.status === 200) {
console.log('Article supprimé avec succÚs');
}
async/await avec try/catch pour une meilleure
lisibilité et gestion d'erreurs cohérente.
3. Configuration
Axios offre de nombreuses options de configuration, passĂ©es soit globalement, soit par requĂȘte,
soit via une instance personnalisée créée avec axios.create().
Objet de configuration
// Toutes les options courantes
const config = {
baseURL: 'https://api.monservice.com', // préfixe pour toutes les URLs
timeout: 5000, // annulation si > 5 secondes
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer mon-token-jwt'
},
params: { // paramĂštres de query string
page: 1,
limit: 20
},
responseType: 'json', // 'blob', 'stream', 'text'...
withCredentials: false // envoyer cookies cross-origin
};
const response = await axios.get('/users', config);
axios.create() â Instance personnalisĂ©e
// Créer une instance préconfigurée (pattern recommandé)
const apiClient = axios.create({
baseURL: 'https://jsonplaceholder.typicode.com',
timeout: 8000,
headers: {
'Content-Type': 'application/json',
'X-Custom-Header': 'ma-valeur'
}
});
// Utiliser l'instance comme axios normal
const users = await apiClient.get('/users');
const post = await apiClient.post('/posts', { title: 'Test', userId: 1 });
// Avantage : chaque service peut avoir sa propre instance
const authApi = axios.create({ baseURL: 'https://auth.monsite.com', timeout: 3000 });
const dataApi = axios.create({ baseURL: 'https://data.monsite.com', timeout: 10000 });
ParamĂštres de query â params
// Axios sérialise automatiquement l'objet params en query string
// params: { page: 2, limit: 10 } â ?page=2&limit=10
const response = await axios.get('https://dummyjson.com/products', {
params: {
limit: 10,
skip: 20,
select: 'title,price,category'
}
});
// URL finale : https://dummyjson.com/products?limit=10&skip=20&select=title,price,category
axios.create() dans vos projets réels. Cela centralise la configuration
(baseURL, headers, timeout) et évite de répéter ces informations à chaque appel.
4. Réponse et Erreurs
Axios retourne un objet response structuré. En cas d'erreur HTTP (4xx, 5xx) ou réseau,
la Promise est rejetée avec un objet error enrichi.
Structure de l'objet response
const response = await axios.get('/posts/1');
console.log(response.data); // corps de la réponse (JSON parsé)
console.log(response.status); // 200, 201, 204...
console.log(response.statusText); // "OK"
console.log(response.headers); // en-tĂȘtes de la rĂ©ponse
console.log(response.config); // config de la requĂȘte originale
console.log(response.request); // objet XMLHttpRequest (navigateur)
Gestion d'erreurs â try/catch
async function chargerPost(id) {
try {
const response = await axios.get(`/posts/${id}`);
return response.data;
} catch (error) {
if (error.response) {
// Erreur HTTP : le serveur a répondu avec un code d'erreur
console.error('Erreur HTTP :', error.response.status);
console.error('Message :', error.response.data);
// 404 â ressource introuvable
// 401 â non authentifiĂ©
// 403 â non autorisĂ©
// 500 â erreur serveur
} else if (error.request) {
// RequĂȘte envoyĂ©e mais pas de rĂ©ponse (timeout, rĂ©seau coupĂ©)
console.error('Pas de réponse du serveur :', error.request);
} else {
// Erreur lors de la configuration de la requĂȘte
console.error('Erreur de configuration :', error.message);
}
throw error; // re-lancer pour que l'appelant puisse gérer
}
}
axios.isAxiosError() â Typage de l'erreur
try {
await axios.get('/utilisateur/999');
} catch (error) {
if (axios.isAxiosError(error)) {
// On sait que c'est une erreur Axios
console.log('Status :', error.response?.status);
console.log('URL :', error.config?.url);
if (error.response?.status === 404) {
afficherMessage('Ressource introuvable');
} else if (error.response?.status >= 500) {
afficherMessage('Erreur serveur â rĂ©essayez plus tard');
}
}
}
fetch, Axios rejette automatiquement la Promise pour les codes HTTP
4xx et 5xx. Avec fetch, il faut vérifier response.ok manuellement.
5. Intercepteurs
Les intercepteurs permettent d'exĂ©cuter du code avant chaque requĂȘte ou aprĂšs chaque rĂ©ponse. Parfaits pour l'authentification, le logging, ou la gestion centralisĂ©e des erreurs.
Intercepteur de requĂȘte
// Ajouter automatiquement le token JWT Ă chaque requĂȘte
axios.interceptors.request.use(
(config) => {
// ExĂ©cutĂ© AVANT l'envoi de la requĂȘte
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
console.log(`â ${config.method?.toUpperCase()} ${config.url}`);
return config; // IMPORTANT : toujours retourner config
},
(error) => {
// Erreur lors de la configuration
return Promise.reject(error);
}
);
Intercepteur de réponse
// Gestion centralisée des erreurs d'authentification
axios.interceptors.response.use(
(response) => {
// Exécuté pour toute réponse 2xx
console.log(`â ${response.status} ${response.config.url}`);
return response; // IMPORTANT : toujours retourner response
},
(error) => {
// Exécuté pour toute erreur HTTP
if (error.response?.status === 401) {
// Token expirĂ© â rediriger vers la page de connexion
localStorage.removeItem('token');
window.location.href = '/login';
}
if (error.response?.status === 429) {
// Rate limiting â attendre et rĂ©essayer
console.warn('Trop de requĂȘtes â rĂ©essayez dans quelques secondes');
}
return Promise.reject(error);
}
);
Intercepteurs sur une instance
const api = axios.create({ baseURL: 'https://api.example.com' });
// Intercepteurs spécifiques à cette instance
const requestInterceptor = api.interceptors.request.use(config => {
config.headers['X-Request-Time'] = Date.now().toString();
return config;
});
// Supprimer un intercepteur si nécessaire
api.interceptors.request.eject(requestInterceptor);
6. Annulation de RequĂȘtes
Annuler une requĂȘte en cours est essentiel pour les performances : Ă©viter les race conditions lors d'une recherche en temps rĂ©el, annuler les requĂȘtes pendantes lors d'un changement de page, ou respecter les timeouts dĂ©finis par l'utilisateur.
AbortController avec Axios
// AbortController â standard Web API, supportĂ© par Axios
const controller = new AbortController();
// Passer le signal Ă la requĂȘte
axios.get('https://jsonplaceholder.typicode.com/posts', {
signal: controller.signal
}).then(response => {
console.log('Données reçues :', response.data.length, 'posts');
}).catch(error => {
if (axios.isCancel(error) || error.name === 'CanceledError') {
console.log('RequĂȘte annulĂ©e');
} else {
console.error('Erreur :', error.message);
}
});
// Annuler aprĂšs 2 secondes
setTimeout(() => {
controller.abort();
console.log('RequĂȘte annulĂ©e manuellement');
}, 2000);
Cas pratique â Recherche en temps rĂ©el
let controllerRecherche = null;
async function rechercherProduits(terme) {
// Annuler la requĂȘte prĂ©cĂ©dente si elle existe encore
if (controllerRecherche) {
controllerRecherche.abort();
}
controllerRecherche = new AbortController();
try {
const response = await axios.get('https://dummyjson.com/products/search', {
params: { q: terme },
signal: controllerRecherche.signal
});
afficherResultats(response.data.products);
} catch (error) {
if (error.name !== 'CanceledError') {
console.error('Erreur de recherche :', error.message);
}
}
}
// Dans un input de recherche
document.getElementById('recherche').addEventListener('input', (e) => {
rechercherProduits(e.target.value);
});
Timeout avec annulation automatique
// Annulation automatique aprĂšs N millisecondes
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000); // 5s
try {
const response = await axios.get('https://api.exemple.com/data', {
signal: controller.signal
});
clearTimeout(timeoutId); // Annuler le timeout si succĂšs
return response.data;
} catch (error) {
if (error.name === 'CanceledError') {
console.error('La requĂȘte a expirĂ© aprĂšs 5 secondes');
}
throw error;
}
useEffect cleanup / onUnmounted) pour éviter les fuites mémoire.