Skip to content

Une promesse en Javascript (Promise)

Qu'est-ce qu'une Promesse ?

Une Promesse en JavaScript est un objet qui représente la fin ou l'échec éventuel d'une opération asynchrone. Une promesse est donc un conteneur pour une valeur qui n'est peut-être pas encore disponible. Elle peut se trouver dans l'un des trois états suivants:

  1. En attente (Pending) : L'état initial, ni accomplie ni rejetée.
  2. Résolue (Fulfilled) : L'opération a abouti avec succès.
  3. Rejetée (Rejected) : L'opération a échoué.

Comment fonctionne une Promesse ?

Créons une Promesse simple pour illustrer son fonctionnement.

javascript
let maPromesse = new Promise((resolve, reject) => {
    let toutVaBien = true;
    
    if(toutVaBien) {
        resolve('La promesse est résolue !');
    } else {
        reject('La promesse est rejetée.');
    }
});
let maPromesse = new Promise((resolve, reject) => {
    let toutVaBien = true;
    
    if(toutVaBien) {
        resolve('La promesse est résolue !');
    } else {
        reject('La promesse est rejetée.');
    }
});

Ici, maPromesse est une nouvelle instance de Promise. La promesse prend une fonction comme argument qui a elle-même deux arguments : resolve et reject.

  • resolve est une fonction que vous appelez lorsque vous souhaitez résoudre la promesse avec succès.
  • reject est une fonction que vous appelez lorsque vous souhaitez signaler un échec.

Dans notre exemple, si toutVaBien est true, nous "résolvons" la promesse avec un message. Si toutVaBien est false, nous "rejetons" la promesse avec un autre message.

Comment utiliser une Promesse ?

Une fois que vous avez une promesse, vous pouvez utiliser .then() pour attacher des callbacks qui s'exécuteront une fois que la promesse est résolue. Si la promesse est rejetée, vous pouvez utiliser .catch().

javascript
maPromesse
    .then(message => {
        console.log(message); // Affiche : 'La promesse est résolue !'
    })
    .catch(erreur => {
        console.log(erreur); // Ne sera pas affiché ici car la promesse est résolue
    });
maPromesse
    .then(message => {
        console.log(message); // Affiche : 'La promesse est résolue !'
    })
    .catch(erreur => {
        console.log(erreur); // Ne sera pas affiché ici car la promesse est résolue
    });

Pourquoi utiliser des Promesses ?

Les promesses offrent une manière plus propre et structurée de gérer les opérations asynchrones par rapport aux callbacks traditionnels. Elles permettent d'éviter ce qu'on appelle "l'enfer des callbacks" où vous vous retrouvez avec de nombreux niveaux d'indentation à cause des callbacks imbriqués.

Enfer des callbacks

Avant l'arrivée des promesses en JavaScript, les développeurs utilisaient principalement des callbacks pour gérer l'asynchronicité. Toutefois, l'utilisation excessive des callbacks peut entraîner un problème communément appelé "l'enfer des callbacks" ou "callback hell".

Imaginez que vous avez une suite d'opérations asynchrones à effectuer, chacune dépendant de la précédente. Avec les callbacks, votre code pourrait ressembler à ceci :

javascript
operation1(function(result1) {
    operation2(result1, function(result2) {
        operation3(result2, function(result3) {
            // ... et cela peut continuer ainsi indéfiniment
        }, function(error3) {
            console.error(error3);
        });
    }, function(error2) {
        console.error(error2);
    });
}, function(error1) {
    console.error(error1);
});
operation1(function(result1) {
    operation2(result1, function(result2) {
        operation3(result2, function(result3) {
            // ... et cela peut continuer ainsi indéfiniment
        }, function(error3) {
            console.error(error3);
        });
    }, function(error2) {
        console.error(error2);
    });
}, function(error1) {
    console.error(error1);
});

Comme vous pouvez le voir, ce code devient rapidement difficile à lire et à maintenir, d'où le terme "l'enfer des callbacks". Avec l'introduction des promesses, la même série d'opérations peut être écrite de manière beaucoup plus claire :

javascript
operation1()
    .then(result1 => operation2(result1))
    .then(result2 => operation3(result2))
    .catch(error => {
        console.error(error);
    });
operation1()
    .then(result1 => operation2(result1))
    .then(result2 => operation3(result2))
    .catch(error => {
        console.error(error);
    });

Le code est plus linéaire et plus facile à suivre.

Utiliser async/await avec les Promesses

D'accord, reprenons l'exemple initial avec maPromesse et intégrons-le dans un contexte utilisant async et await. Nous allons définir une fonction asynchrone et attendre que maPromesse soit résolue à l'intérieur de cette fonction:

javascript
async function traiterPromesse() {
    try {
        let resultat = await maPromesse;
        console.log(resultat); // Affichera : 'La promesse est résolue !'
    } catch (erreur) {
        console.error(erreur); // Ne sera pas affiché ici car la promesse est résolue
    }
}

traiterPromesse();
async function traiterPromesse() {
    try {
        let resultat = await maPromesse;
        console.log(resultat); // Affichera : 'La promesse est résolue !'
    } catch (erreur) {
        console.error(erreur); // Ne sera pas affiché ici car la promesse est résolue
    }
}

traiterPromesse();

Dans l'exemple ci-dessus, await maPromesse "met en pause" la fonction traiterPromesse jusqu'à ce que maPromesse soit résolue. Si maPromesse est résolue avec succès, le résultat est affecté à la variable resultat. Si maPromesse est rejetée, le code dans le bloc catch sera exécuté.

L'utilisation d'async et await offre une syntaxe claire et linéaire, qui est très similaire à la façon dont nous écrivons le code synchrone, rendant ainsi le code asynchrone plus lisible et compréhensible.