Skip to content

Chapitre 4.5 : Async/await vs Promise

Temps d'étude : 30 minutes


1. Asynchronisme : Deux manières de gérer la "communication spatiale"

Imaginez que le Centre de Contrôle de Mission (CCM) envoie une commande à Mars. La réponse n'arrivera que dans quelques minutes. Comment organiser le travail pendant ce temps ?

Méthode 1 : "Protocole de rappel" (Promise avec .then()) Vous envoyez une commande et donnez l'instruction : "QUAND la réponse arrivera, ALORS exécute cette fonction". Cela ressemble à une chaîne d'événements.

Méthode 2 : "Mode d'attente" (Async/await) Vous dites : "Je VAIS ATTENDRE la réponse à cette commande, mais je ne bloquerai pas les autres pupitres de commande". C'est comme si vous mettiez en pause l'exécution de cette tâche spécifique, permettant au reste du CCM de continuer à fonctionner.

Les deux méthodes résolvent la même tâche : la gestion des opérations asynchrones. async/await est simplement une syntaxe plus moderne et lisible qui fonctionne "au-dessus" des promesses.

💡 Analogie spatiale :

  • Promise avec .then() : C'est comme écrire sur un post-it : "Quand le rover martien enverra la photo, la transmettre au département d'analyse."
  • Async/await : C'est comme dire à un assistant : "Attendez la photo du rover martien, pendant ce temps je m'occupe des calculs pour le lancement d'une nouvelle fusée."

2. Promise avec .then() : La chaîne de commandes classique

C'est la manière fondamentale de travailler avec l'asynchronisme en JavaScript, que nous avons utilisée au chapitre 4.1.

Rappelons notre premier code :

function getIssPositionWithPromises() {
    console.log('Envoi de la requête via le protocole "Promise"...');

    fetch('http://api.open-notify.org/iss-now.json')
        .then(response => {
            // Étape 1 : Réponse reçue
            if (!response.ok) {
                throw new Error(`Erreur HTTP : ${response.status}`);
            }
            return response.json(); // On retourne une nouvelle promesse
        })
        .then(data => {
            // Étape 2 : Données parsées
            console.log('Données via le protocole "Promise" reçues :', data.iss_position);
        })
        .catch(error => {
            // Étape 3 (Erreur) : Quelque chose s'est mal passé à l'une des étapes
            console.error('Panne de communication via le protocole "Promise" :', error);
        });

    console.log('...commande envoyée, le CCM continue son travail...');
}

Avantages :

  • Chaîne d'actions explicite.
  • Convient bien aux opérations séquentielles simples.

Inconvénients :

  • "Enfer des rappels" (Callback Hell) : Avec un grand nombre d'opérations asynchrones imbriquées, le code peut se transformer en une "échelle" de .then() difficile à lire.
  • La gestion des erreurs peut être moins intuitive.

3. Async/await : Le style synchrone moderne

async/await est du "sucre syntaxique" au-dessus des promesses, qui permet d'écrire du code asynchrone comme s'il était synchrone.

Règles d'utilisation :

  1. Le mot-clé await ne peut être utilisé qu'à l'intérieur d'une fonction marquée comme async.
  2. await est placé devant un appel qui retourne une promesse (par exemple, fetch() ou response.json()).
  3. await "suspend" l'exécution de la fonction async jusqu'à ce que la promesse soit résolue, et retourne son résultat.

Le même code, réécrit avec async/await :

async function getIssPositionWithAsyncAwait() {
    console.log('Envoi de la requête via le protocole "Async/await"...');

    try {
        // Étape 1 : On attend la réponse du serveur
        const response = await fetch('http://api.open-notify.org/iss-now.json');

        if (!response.ok) {
            throw new Error(`Erreur HTTP : ${response.status}`);
        }

        // Étape 2 : On attend que le corps de la réponse soit converti en JSON
        const data = await response.json();

        console.log('Données via le protocole "Async/await" reçues :', data.iss_position);
    } catch (error) {
        // Étape 3 (Erreur) : On attrape toute erreur du bloc try
        console.error('Panne de communication via le protocole "Async/await" :', error);
    }

    console.log('...commande envoyée, le CCM continue son travail...');
}

Avantages :

  • Lisibilité : Le code ressemble presque à du code synchrone ordinaire, il est facile à lire de haut en bas.
  • Gestion des erreurs : Utilise le bloc try...catch standard et familier.
  • Débogage : Beaucoup plus facile à déboguer, car on peut placer des points d'arrêt (breakpoints) sur chaque ligne avec await.

Inconvénients :

  • Facile d'oublier await ou async, ce qui entraînera des erreurs.

4. Quand utiliser quel protocole ?

Situation Approche recommandée Pourquoi ?
La plupart des cas async/await Code plus propre, plus facile à lire et à déboguer. C'est le standard moderne.
Chaîne simple de 1-2 actions Promise avec .then() Convient parfaitement, le code reste compact.
Exécution parallèle de plusieurs requêtes Promise.all() Cette méthode permet de lancer plusieurs promesses simultanément et d'attendre qu'elles se terminent toutes. async/await se combine parfaitement avec elle.

Exemple avec Promise.all() :

async function getParallelData() {
    try {
        // On lance les deux requêtes simultanément
        const [shipsResponse, launchesResponse] = await Promise.all([
            fetch('https://api.spacexdata.com/v4/rockets'),
            fetch('https://api.spacexdata.com/v4/launches/latest')
        ]);

        if (!shipsResponse.ok || !launchesResponse.ok) {
            throw new Error('Une des requêtes a échoué !');
        }

        const rockets = await shipsResponse.json();
        const latestLaunch = await launchesResponse.json();

        console.log(`Nombre total de fusées dans la flotte : ${rockets.length}`);
        console.log(`Dernier lancement : ${latestLaunch.name}`);
    } catch (error) {
        console.error('Erreur lors de la récupération des données parallèles :', error);
    }
}


Quiz pour la consolidation

1. `async/await` est...

2. Quel mot-clé est obligatoire pour une fonction à l'intérieur de laquelle `await` est utilisé ?

3. Le principal avantage d' `async/await` par rapport à `.then()` :

4. Que se passe-t-il si vous oubliez `await` avant `fetch()` à l'intérieur d'une fonction `async` ?

5. `Promise.all()` est utilisé pour :


🚀 Résumé du chapitre :

Vous avez appris deux syntaxes pour gérer les opérations asynchrones et compris pourquoi async/await est préférable dans la plupart des projets modernes.

  • 🔗 Vous avez rafraîchi vos connaissances sur les Promise avec .then().
  • 🛠️ Vous avez profondément compris comment fonctionne async/await et ses avantages.
  • ⚡ Vous avez découvert Promise.all pour l'exécution de requêtes parallèles.

Les protocoles de communication ont été étudiés ! Dans le dernier chapitre de cette section, nous rassemblerons toutes nos connaissances et achèverons notre "Centre de Contrôle de Mission", en créant une interface complète pour toutes les opérations CRUD.

📌 Pratique :

  • Réécrivez toutes les fonctions de votre app.js qui utilisent encore .then(), en utilisant la syntaxe async/await.
  • Essayez d'ajouter une autre requête à Promise.all() (par exemple, vers https://api.spacexdata.com/v4/starlink) et d'afficher les données.

⚠️ En cas d'erreurs :

  • await is only valid in async functions : Assurez-vous que la fonction où vous utilisez await est marquée comme async.
  • La variable contient [object Promise] : Vous avez oublié de placer await devant la fonction qui retourne une promesse.