0 XP
?
Intermédiaire45 min30 XP

Objectifs de cette leçon

  • Créer une Promise
  • Utiliser then/catch/finally
  • Comprendre l'ordre d'exécution asynchrone

Promesses en JavaScript 🤞

Les promesses gerent les operations asynchrones : appels reseau, lecture de fichiers, delais... Elles representent une valeur qui sera disponible maintenant, plus tard, ou jamais.


1. Pourquoi les promesses ? 🤔

// ❌ Callback hell (cauchemar)
fetchUser(id, (user) => {
    getOrders(user.id, (orders) => {
        getOrderDetails(orders[0].id, (details) => {
            console.log(details);
            // Imbrication infinie...
        });
    });
});

// ✅ Avec Promesses
fetchUser(id)
    .then(user => getOrders(user.id))
    .then(orders => getOrderDetails(orders[0].id))
    .then(details => console.log(details))
    .catch(error => console.error(error));

2. Creer une promesse 🏗️

const maPromesse = new Promise((resolve, reject) => {
    // Code asynchrone ici
    const succes = true;

    if (succes) {
        resolve("Operation reussie !");  // Promesse tenue
    } else {
        reject(new Error("Echec !"));   // Promesse rompue
    }
});

// Utiliser la promesse
maPromesse
    .then(resultat => {
        console.log(resultat); // "Operation reussie !"
    })
    .catch(erreur => {
        console.error(erreur.message); // "Echec !"
    });

Trois etats d'une promesse

EtatDescriptionResultat
Pending (en attente)L'operation n'est pas finieAucun
Fulfilled (tenue)L'operation a reussiresolve(valeur)
Rejected (rompue)L'operation a echouereject(erreur)

3. then, catch, finally 🔄

function fetchUser(id) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (id > 0) {
                resolve({ id, nom: "Alice", email: "alice@email.com" });
            } else {
                reject(new Error("ID invalide"));
            }
        }, 1000);
    });
}

fetchUser(1)
    .then(user => {
        console.log("Utilisateur :", user.nom);
        return user.email; // La valeur retournee devient la valeur du then suivant
    })
    .then(email => {
        console.log("Email :", email);
    })
    .catch(erreur => {
        console.error("Erreur :", erreur.message);
    })
    .finally(() => {
        console.log("Operation terminee (succes ou echec)");
    });

💡 finally s'execute toujours, que la promesse soit tenue ou rompue. Utile pour le nettoyage.


4. Promesses imbriquees et chaining 📦

function fetchUser(id) {
    return new Promise(resolve => {
        setTimeout(() => resolve({ id, nom: "Alice" }), 1000);
    });
}

function fetchPosts(userId) {
    return new Promise(resolve => {
        setTimeout(() => resolve([
            { id: 1, titre: "Post 1" },
            { id: 2, titre: "Post 2" }
        ]), 1000);
    });
}

// Chaining
fetchUser(1)
    .then(user => {
        console.log("User :", user.nom);
        return fetchPosts(user.id); // Retourne une nouvelle promesse
    })
    .then(posts => {
        console.log("Posts :", posts.length);
    })
    .catch(err => {
        console.error("Erreur :", err);
    });

5. Promise.all — executer en parallele ⚡

const promesse1 = fetch("https://api.example.com/users").then(r => r.json());
const promesse2 = fetch("https://api.example.com/posts").then(r => r.json());
const promesse3 = fetch("https://api.example.com/comments").then(r => r.json());

// Tout execute en parallele, on attend les 3
Promise.all([promesse1, promesse2, promesse3])
    .then(([users, posts, comments]) => {
        console.log("Users :", users.length);
        console.log("Posts :", posts.length);
        console.log("Comments :", comments.length);
    })
    .catch(erreur => {
        // Si UNE SEULE promesse echoue, tout echoue
        console.error("Une erreur :", erreur);
    });

⚠️ Promise.all echoue completement si une seule promesse echoue. Utilise Promise.allSettled pour ignorer les echecs.


6. Promise.allSettled — sans echec 🛡️

const promesses = [
    Promise.resolve("Succes 1"),
    Promise.reject(new Error("Echec")),
    Promise.resolve("Succes 2")
];

Promise.allSettled(promesses)
    .then(resultats => {
        resultats.forEach(r => {
            if (r.status === "fulfilled") {
                console.log("Succes :", r.value);
            } else {
                console.log("Echec :", r.reason.message);
            }
        });
    });
// Affiche :
// Succes : Succes 1
// Echec : Echec
// Succes : Succes 2

7. Promise.race — le premier arrive gagne 🏁

function timeout(ms) {
    return new Promise((_, reject) => {
        setTimeout(() => reject(new Error("Timeout !")), ms);
    });
}

const fetchAvecTimeout = Promise.race([
    fetch("https://api.example.com/data"),
    timeout(5000) // Timeout apres 5 secondes
]);

fetchAvecTimeout
    .then(reponse => console.log("Donnees recues"))
    .catch(erreur => console.error(erreur.message)); // "Timeout !" si > 5s

8. Promise.any — le premier succes 🏆

const promesses = [
    fetch("https://api1.example.com/data"),
    fetch("https://api2.example.com/data"),
    fetch("https://api3.example.com/data")
];

// Le premier succes est utilise
Promise.any(promesses)
    .then(reponse => {
        console.log("Premiere reponse recue :", reponse);
    })
    .catch(AggregateError => {
        // Toutes les promesses ont echoue
        console.error("Toutes les sources ont echoue");
    });

9. La microtask queue et l'ordre d'execution ⏱️

console.log("1. Debut");

setTimeout(() => {
    console.log("2. setTimeout (macrotache)");
}, 0);

Promise.resolve().then(() => {
    console.log("3. Promise.then (microtache)");
});

console.log("4. Fin");

// Resultat :
// 1. Debut
// 4. Fin
// 3. Promise.then (microtache)
// 2. setTimeout (macrotache)

💡 Ordre de priorite :

  1. Code synchrone (s'execute immediatement)
  2. Microtaches (Promises — then, catch, finally)
  3. Macrotaches (setTimeout, setInterval, I/O)
setTimeout(() => console.log("1"), 0);
Promise.resolve().then(() => console.log("2"));
Promise.resolve().then(() => console.log("3"));
setTimeout(() => console.log("4"), 0);

// Resultat : 2, 3, 1, 4
// Les microtaches (2, 3) passent AVANT les macrotaches (1, 4)

10. Exemple concret : fetch API 🌐

// GET simple
fetch("https://jsonplaceholder.typicode.com/users/1")
    .then(reponse => {
        if (!reponse.ok) {
            throw new Error(`Erreur HTTP : ${reponse.status}`);
        }
        return reponse.json();
    })
    .then(donnees => {
        console.log("Utilisateur :", donnees.name);
    })
    .catch(erreur => {
        console.error("Erreur :", erreur.message);
    });

// POST avec donnees
fetch("https://jsonplaceholder.typicode.com/posts", {
    method: "POST",
    headers: {
        "Content-Type": "application/json"
    },
    body: JSON.stringify({
        titre: "Nouveau post",
        corps: "Contenu du post",
        userId: 1
    })
})
    .then(r => r.json())
    .then(donnees => console.log("Cree :", donnees));

11. Exercices pour toi 🎯

Exercice 1 : Delai avec promesse Cree une function delai(ms) qui retourne une promesse qui se resout apres ms millisecondes.

Exercice 2 : Retry Cree une function fetchAvecRetry(url, tentatives) qui reessaie l'appel en cas d'echec.

Exercice 3 : Serie de promesses Execute 3 fetch en serie (le 2em depend du 1er) avec gestion d'erreur globale.

⚡ Simulateur — Promesses

Étape 1/6
📝 Pseudo-code
1const promesse = new Promise((resolve, reject) => {
2 setTimeout(() => resolve("Données reçues !"), 1000);
3});
4promesse.then(data => console.log(data));
5console.log("Après la promesse");
⚙️ Exécution
📦 Mémoire
promesse
Promise { pending }
🔀 Flux d'exécution
new Promise()
3
Création de la promesse

new Promise() crée une promesse. La fonction exécuteur reçoit resolve et reject. La promesse est en état "pending" (en attente).