11

Programmation Asynchrone

Event Loop, Callbacks & Timers

JavaScript est single-threaded mais peut gérer des opérations asynchrones grâce à l'Event Loop. Comprendre ce mécanisme est essentiel.

🔄 L'Event Loop

L'Event Loop permet à JavaScript d'exécuter du code asynchrone sans bloquer le thread principal.

📊 Architecture de l'Event Loop

📚 Call Stack
Pile d'exécution (LIFO)
main()
⏱️ Task Queue (Macrotasks)
setTimeout, setInterval, I/O
Vide
⚡ Microtask Queue
Promises, queueMicrotask
Vide
Ordre d'exécution :
1️⃣ Call Stack : Code synchrone
2️⃣ Microtasks : Promises (priorité haute)
3️⃣ Macrotasks : setTimeout, setInterval (priorité basse)

⏱️ Timers : setTimeout & setInterval

// setTimeout : Exécute UNE FOIS après délai
setTimeout(() => {
    console.log('Exécuté après 1 seconde');
}, 1000);

// setInterval : Exécute RÉPÉTITIVEMENT
const intervalId = setInterval(() => {
    console.log('Toutes les 2 secondes');
}, 2000);

// ⚠️ TOUJOURS nettoyer les intervals !
clearInterval(intervalId);

// Pattern : Auto-nettoyage
const id = setInterval(() => {
    console.log('Tick');
    if (condition) clearInterval(id);
}, 1000);

// setTimeout avec 0ms : Reporte à la prochaine itération
setTimeout(() => console.log('Async'), 0);
console.log('Sync'); // S'exécute AVANT
// Output: "Sync" puis "Async"

😱 Callback Hell vs Solutions Modernes

❌ Callback Hell (Pyramid of Doom)
getData(function(a) {
    getMoreData(a, function(b) {
        getMoreData(b, function(c) {
            getMoreData(c, function(d) {
                getMoreData(d, function(e) {
                    // 😱 Illisible !
                });
            });
        });
    });
});
✅ Async/Await (Moderne)
async function fetchData() {
    const a = await getData();
    const b = await getMoreData(a);
    const c = await getMoreData(b);
    const d = await getMoreData(c);
    const e = await getMoreData(d);
    // ✅ Lisible, séquentiel
}

🎮 Playground : Ordre d'Exécution

Prédisez l'ordre d'exécution, puis vérifiez !

console.log('1: Sync');

setTimeout(() => console.log('2: Macro (setTimeout)'), 0);

Promise.resolve().then(() => console.log('3: Micro (Promise)'));

console.log('4: Sync');

queueMicrotask(() => console.log('5: Micro (queueMicrotask)'));

// Quel est l'ordre d'affichage ?
Cliquez sur Exécuter pour voir l'ordre

⚡ Microtasks vs Macrotasks

Type Exemples Priorité
Microtasks Promise.then, queueMicrotask, MutationObserver Haute
Macrotasks setTimeout, setInterval, setImmediate, I/O Basse
Best Practice : Les Microtasks (Promises) s'exécutent AVANT les Macrotasks (setTimeout). Utilisez queueMicrotask() pour du code prioritaire. Nettoyez toujours vos setInterval avec clearInterval().
← Events Suivant: Fetch & API →