Promesses et async/await en JavaScript
Callbacks, Promises, then/catch, async/await, Promise.all — l'asynchrone maîtrisé
SECTION 01
Pourquoi l'asynchrone ?
JavaScript n'exécute qu'une seule chose à la fois. Sans asynchrone, une requête réseau de 3 secondes bloquerait tout le navigateur. L'asynchrone permet de lancer une opération et de continuer le code en attendant le résultat.
const data = readFileSync(« data.json »); // attend… attend… attend…
console.log(data); // exécuté après la lecture// Asynchrone — NON BLOQUANT
fetch(« https://api.example.com/data »); // lancé, on continue
console.log(« Ceci s'affiche IMMÉDIATEMENT »);
Les opérations asynchrones typiques : requêtes HTTP (fetch), timers (setTimeout), lecture de fichiers, accès base de données.
SECTION 02
Les callbacks (l'ancien monde)
Avant les Promises, on utilisait des callbacks — une fonction passée en argument, exécutée quand l'opération est terminée :
setTimeout(() => , 2000);// Callback Hell — enchaîner des opérations imbriquées
getUser(id, (user) => );
Le Callback Hell (pyramid of doom) rend le code illisible et la gestion d'erreurs cauchemardesque. Les Promises résolvent ce problème.
SECTION 03
Les Promises
Une Promise représente une valeur qui n'existe pas encore. Elle a 3 états :
| État | Signification |
|---|---|
| pending | En attente — l'opération est en cours |
| fulfilled | Résolue — l'opération a réussi (valeur disponible) |
| rejected | Rejetée — l'opération a échoué (erreur disponible) |
const maPromise = new Promise((resolve, reject) => );
// fetch() retourne une Promise
const response = fetch(« https://api.example.com/data »);
// response est une Promise (pending → fulfilled ou rejected)
SECTION 04
then / catch / finally
.then(response => response.json()) // fulfilled → transformer
.then(users => )
.catch(error => )
.finally(() => );
.then() chaîne les opérations (chaque then retourne une nouvelle Promise). .catch() attrape les erreurs de toute la chaîne. .finally() s'exécute dans tous les cas (comme un bloc finally en try/catch).
getUser(id)
.then(user => getOrders(user.id))
.then(orders => getProduct(orders[0].productId))
.then(product => console.log(product))
.catch(error => console.error(error));
Plat, lisible, une seule gestion d'erreurs. Mais on peut faire encore mieux avec async/await.
SECTION 05
async / await
async/await (ES2017) est du sucre syntaxique au-dessus des Promises. Ça fait exactement la même chose, mais avec une syntaxe plus lisible.
// await « attend » qu'une Promise se résolveasync function loadUser()
// Même chose en arrow function
const loadUser = async () => ;
// Le callback hell devient :
async function getProductInfo(id)
await ne peut être utilisé que dans une fonction async (ou au top-level d'un module ES). Une fonction async retourne toujours une Promise.
SECTION 06
Gestion des erreurs
⚠️ fetch ne rejette pas sur les erreurs HTTP (404, 500). Il faut vérifier response.ok manuellement. fetch rejette uniquement sur les erreurs réseau (pas de connexion, DNS fail).
SECTION 07
Promise.all, race, allSettled
const [users, posts, comments] = await Promise.all([
fetch(« /api/users »).then(r => r.json()),
fetch(« /api/posts »).then(r => r.json()),
fetch(« /api/comments »).then(r => r.json()),
]);
// Les 3 requêtes sont lancées EN PARALLÈLE !
// Si UNE échoue → tout échoue (catch)// Promise.allSettled — attend toutes, même les échecs
const results = await Promise.allSettled([
fetch(« /api/users »),
fetch(« /api/broken »), // peut échouer
]);
// [, ]
// Promise.race — la première qui se résout (ou rejette)
const fastest = await Promise.race([
fetch(« /api/server1 »),
fetch(« /api/server2 »),
]);
// Promise.any — la première qui RÉUSSIT (ignore les rejets)
const first = await Promise.any([
fetch(« /api/primary »),
fetch(« /api/fallback »),
]);
| Méthode | Attend | Échoue si |
|---|---|---|
| Promise.all | Toutes fulfilled | Une seule rejected |
| Promise.allSettled | Toutes terminées | Jamais (retourne tous les résultats) |
| Promise.race | La première terminée | Si la première est rejected |
| Promise.any | La première fulfilled | Si toutes sont rejected |
SECTION 08
Patterns courants
const users = await fetch(« /users »); // 1s
const posts = await fetch(« /posts »); // 1s → total: 2s// ✅ PARALLÈLE — les deux en même temps (rapide)
const [users, posts] = await Promise.all([
fetch(« /users »), // 1s
fetch(« /posts »), // 1s → total: 1s
]);
Si les requêtes sont indépendantes, lance-les en parallèle avec Promise.all. Ne les séquence avec await que si le résultat de l'une est nécessaire pour lancer l'autre.
SECTION 09
Erreurs fréquentes
| Erreur | Problème | Solution |
|---|---|---|
| Oublier await | On récupère la Promise, pas la valeur | Toujours await devant un appel async |
| await séquentiel inutile | Requêtes indépendantes lancées une par une | Promise.all() pour le parallèle |
| Pas de try/catch | Erreurs non gérées (unhandled rejection) | Toujours entourer d'un try/catch |
| Ne pas vérifier response.ok | fetch ne rejette pas sur 404/500 | if (!response.ok) throw … |
| Mélanger .then() et await | Code confus et incohérent | Choisir un style et s'y tenir |
SECTION 10
Questions fréquentes
🌐 Fetch API
🔤 let, const, var
➡️ Fonctions fléchées
📄 JSON
🎯 addEventListener
⚡ Cours JavaScript complet
🏠 Hub Programmation
Promesses et async/await en JavaScript — Guide complet
Référence : MDN Promise · MDN async
