Module JS.8 – Asynchrone
Objectif
Maîtriser la programmation asynchrone JavaScript : setTimeout, Promises, async/await pour gérer les opérations non-bloquantes efficacement.
Théorie
setTimeout et setInterval
setTimeout
Exécute une fonction après un délai.
setTimeout(() => {
console.log("Après 1 seconde");
}, 1000);
// Avec paramètres
setTimeout((nom, age) => {
console.log(`${nom} a ${age} ans`);
}, 1000, "Jean", 30);
Annuler :
const timerId = setTimeout(() => {
console.log("Ne s'affichera pas");
}, 1000);
clearTimeout(timerId); // Annule l'exécution
setInterval
Exécute une fonction à intervalles réguliers.
const intervalId = setInterval(() => {
console.log("Toutes les secondes");
}, 1000);
// Arrêter
clearInterval(intervalId);
Callbacks et Callback Hell
Problème du callback hell :
chargerDonnees((donnees) => {
traiterDonnees(donnees, (resultat) => {
sauvegarder(resultat, (succes) => {
if (succes) {
afficherNotification(() => {
// Encore plus profond...
});
}
});
});
});
Solution : Promises
Promises
Une Promise représente une valeur qui sera disponible dans le futur.
Création
const promesse = new Promise((resolve, reject) => {
// Opération asynchrone
setTimeout(() => {
const succes = true;
if (succes) {
resolve("Données chargées");
} else {
reject(new Error("Échec"));
}
}, 1000);
});
Utilisation
promesse
.then((resultat) => {
console.log(resultat); // "Données chargées"
return "Traitement terminé";
})
.then((message) => {
console.log(message); // "Traitement terminé"
})
.catch((erreur) => {
console.error("Erreur :", erreur);
})
.finally(() => {
console.log("Toujours exécuté");
});
Chaînage
chargerDonnees()
.then(traiterDonnees)
.then(sauvegarder)
.then(afficherNotification)
.catch(gérerErreur);
Méthodes statiques
Promise.all : Attend que toutes les promises se résolvent
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const p3 = Promise.resolve(3);
Promise.all([p1, p2, p3])
.then((valeurs) => {
console.log(valeurs); // [1, 2, 3]
});
Promise.allSettled : Attend toutes, même les échecs
Promise.allSettled([p1, p2, p3])
.then((resultats) => {
// Tous les résultats, même les rejetés
});
Promise.race : Retourne la première résolue
Promise.race([p1, p2, p3])
.then((premiere) => {
console.log(premiere); // La première résolue
});
Promise.resolve/reject :
Promise.resolve("Valeur"); // Promise résolue immédiatement
Promise.reject(new Error("Erreur")); // Promise rejetée
async/await
Syntaxe moderne pour gérer les Promises de manière synchrone.
async
Une fonction async retourne toujours une Promise.
async function chargerDonnees() {
return "Données chargées";
}
// Équivalent à :
function chargerDonnees() {
return Promise.resolve("Données chargées");
}
await
await pause l'exécution jusqu'à ce que la Promise soit résolue.
async function processus() {
try {
const donnees = await chargerDonnees();
console.log(donnees);
const traitees = await traiterDonnees(donnees);
console.log(traitees);
} catch (erreur) {
console.error("Erreur :", erreur);
}
}
Avantages :
- Code plus lisible (semble synchrone)
- Gestion d'erreurs avec try/catch
- Pas de callback hell
await avec Promise.all
async function chargerTout() {
const [donnees1, donnees2, donnees3] = await Promise.all([
chargerDonnees1(),
chargerDonnees2(),
chargerDonnees3()
]);
// Toutes chargées en parallèle
}
Fetch API
API moderne pour faire des requêtes HTTP.
fetch('https://api.exemple.com/data')
.then(response => {
if (!response.ok) {
throw new Error('Erreur HTTP');
}
return response.json();
})
.then(data => {
console.log(data);
})
.catch(erreur => {
console.error(erreur);
});
Avec async/await :
async function chargerAPI() {
try {
const response = await fetch('https://api.exemple.com/data');
if (!response.ok) {
throw new Error('Erreur HTTP');
}
const data = await response.json();
console.log(data);
} catch (erreur) {
console.error(erreur);
}
}
POST avec données :
async function envoyerDonnees(donnees) {
const response = await fetch('https://api.exemple.com/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(donnees)
});
return await response.json();
}
Event Loop
Comprendre comment JavaScript gère l'asynchrone.
Ordre d'exécution :
- Code synchrone
- Microtasks (Promises, queueMicrotask)
- Macrotasks (setTimeout, setInterval, I/O)
console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));
console.log('4');
// Sortie : 1, 4, 3, 2
// Microtasks avant macrotasks
Exercice
-
setTimeout/setInterval
- Créez des timers
- Testez clearTimeout/clearInterval
- Comprenez le délai minimum
-
Promises
- Créez des Promises
- Chaînez-les avec then/catch
- Utilisez Promise.all, race
-
async/await
- Convertissez des callbacks en async/await
- Gèrez les erreurs avec try/catch
- Utilisez await avec Promise.all
-
Fetch
- Faites des requêtes HTTP
- Gèrez les réponses
- Testez POST avec données
-
Event Loop
- Testez l'ordre d'exécution
- Comprenez microtasks vs macrotasks
- Observez le comportement
Quiz
-
Que retourne une fonction async ?
- La valeur directement
- Une Promise
- undefined
-
Que fait await ?
- Crée une Promise
- Attend la résolution d'une Promise
- Annule une Promise
-
Quelle est la différence entre Promise.all et Promise.race ?
- Aucune différence
- all attend toutes, race la première
- race est plus rapide
-
Que fait fetch() ?
- Charge un fichier local
- Fait une requête HTTP
- Crée une Promise
-
Dans quel ordre s'exécutent microtasks et macrotasks ?
- Macrotasks d'abord
- Microtasks d'abord
- Ordre aléatoire
Mini défi
Mission : Créer un système de chargement de données asynchrone
Créez un système qui charge et traite des données de manière asynchrone :
Fonctionnalités :
-
Simulation de chargement
chargerDonnee(id, delai): Simule un chargement avec setTimeout- Retourne une Promise avec les données
- Gère les erreurs aléatoires
-
Chargement séquentiel
chargerSequenciel(ids): Charge les données une par une- Utilise async/await
- Affiche la progression
-
Chargement parallèle
chargerParallele(ids): Charge toutes en même temps- Utilise Promise.all
- Compare les temps avec séquentiel
-
Gestion d'erreurs
chargerAvecRetry(fonction, maxTentatives): Réessaie en cas d'échec- Utilise async/await
- Gère les erreurs gracieusement
-
Requêtes HTTP réelles
- Utilisez fetch pour charger des données d'une API publique
- Gèrez les erreurs HTTP
- Affichez les résultats
Critères :
- ✅ Utilisation de Promises
- ✅ async/await pour la lisibilité
- ✅ Gestion d'erreurs complète
- ✅ Comparaison séquentiel vs parallèle
- ✅ Code propre et documenté
Objectif : Maîtriser la programmation asynchrone JavaScript et créer des applications réactives.
Validation : Vous pouvez passer au module suivant quand vous maîtrisez Promises, async/await et pouvez gérer l'asynchrone efficacement.