Une promesse, ou en anglais promise, consiste en un engagement à faire quelque chose. Par exemple, un collègue peut promettre de remettre sa partie d’un travail d’ici la fin de la semaine.

Le résultat d’une telle promesse n’est pas immédiatement disponible. Il faut se montrer patient et attendre que la promesse soit complétée. Par exemple, attendre que le collègue remette sa partie, soit: jeudi, vendredi, samedi ou encore dimanche.

Une promesse est faite dans le but d’être respectée. Donc si le collègue en question promet de remettre sa partie pour une date X, c’est qu’il est confiant de pouvoir respecter son engagement et lorsque ce sera chose faite, vous pourrez alors jumeler vos parties.

Dans de rares occasions, une promesse peut être brisée. Un contretemps pourrait par exemple empêcher ledit collègue de remettre sa partie. Vous, vous tournerez alors vers un plan B.

Les Promises en JavaScript fonctionnent sur le même principe. À défaut de pouvoir répondre immédiatement une fonction peut retourner une promesse. Cette approche est particulièrement utile lorsque la fonction en question contacte un serveur externe, puisque son délai de réponse peut varier.

Si la promesse est respectée, la méthode .then() est ensuite appelée et la valeur de la réponse lui est passée en paramètre.

Si la promesse est brisée et qu’une méthode .catch() est présente, elle est appelée et un message d’erreur lui est envoyé.

Bien qu’il soit possible de faire et de recevoir des promesses en JavaScript, il est plus fréquent d’en recevoir.

new Promise

Le code new Promise() permet de créer une promesse. Cette promesse est en fait un objet contenant une fonction acceptant deux paramètres.

  1. Le premier correspond au nom d'une fonction à appeler lorsque la promesse est respectée.

  2. Le deuxième au nom de la fonction à appeler lorsqu'elle est brisée.

Par exemple, la promesse suivante 👇 appelle la fonction resolve lorsqu'elle est respectée et reject lorsqu'elle est brisée. La valeur du retour dans les deux cas est passée en paramètre.

const promesse = new Promise((resolve, reject) => {
  const respectPromesse = true;

  if (respectPromesse === true) {
    resolve("Promesse respectée");
  } else {
    reject("Promesse brisée");
  }
});

Dans le cadre de cette démonstration, la promesse sera toujours respectée.

Cependant, un exemple plus concret serait le cas d'un service tentant de répondre à une demande d'informations. Si les informations sont trouvées, la fonction assignée au respect de la promesse est appelée. Si le délai imparti avant de trouver la réponse est dépassé, la fonction assignée au bris de promesse est appelée.

Pour obtenir le résultat d'une promesse, il est impossible d'appeler directement la promesse.

Par exemple, le code suivant:

console.log(promesse); // [objet Promise] {}

Retournerait un message indiquant qu'il s'agit d'un objet de type Promise et non la valeur contenu dans la promesse.

then() ✅

Si la promesse est respectée, une méthode .then() est appelée et la valeur lui est passée en paramètre.

Par exemple:

promesse
  .then(valeur => console.log(valeur));
// "Promesse respectée"

Une méthode .then() retourne elle aussi une promesse. Cette promesse peut donc à son tour avoir un .then() et ainsi enchainer de multiple .then() un à la suite de l'autre.

Par exemple:

promesse
  .then(value => `${value}, oh oui!!!`)
  .then(msg => console.log(msg)); // "Promesse respectée, oh oui!!!"

catch() 🚫

Si la promesse est brisée et qu'une méthode .catch() est présente, cette dernière est appelée et la valeur lui est passée en paramètre.

Par exemple:

promesse
  .catch(error => console.log(error)); // "Promesse brisée"

finally()

Si une méthode .finally() est présente, celle-ci est appelée dès que la promesse est complétée, peu importe son statut qu'elle soit respectée ou brisée.

Par exemple:

promesse
  .finally(() => console.log("Promesse complétée"));

Dans un exemple concret, tout mis ensemble donnerait ceci:

promesse
  .then(value => console.log(value))
  .catch(error => console.log(error))
  .finally(() => console.log("Promesse complétée"));

// "Promesse respectée", "Promesse complétée"

La relation entre des promesses peut variée. Parfois certaines sont interchangeables, alors qu'à d'autres moments elles sont toutes requises avant de pouvoir passer à l'étape suivante.

Afin de gérer ces relations, l'objet Promise est doté de plusieurs méthodes permettant de retourner à son tour des promesses (promise). Voici deux de ces méthodes les plus communes.

all()

La méthode Promise.all() retourne une promesse respectée lorsque l'ensemble des promesses lui étant passées en paramètres sont respectées. Sa valeur de résultat contient un tableau populé par le résultat de chacune de ses sous-promesses.

const p1 = new Promise(resolve => resolve("Promesse 1"));
const p2 = new Promise(resolve => resolve("Promesse 2"));
const p3 = new Promise(resolve => resolve("Promesse 3"));

Promise.all([p1, p2, p3]).then(values => {
  console.log(values);
});

// ["Promesse 1", "Promesse 2", "Promesse 3"]

any()

Contrairement à la méthode Promise.all(), la méthode Promise.any() retourne une promesse respectée dès qu'une promesse lui étant passées en paramètres est respectée. Sa valeur de résultat contient le résultat de la sous-promesses la plus rapide à répondre.

const p1 = new Promise((resolve) => resolve("Promesse 1")); // 🐢 lente
const p2 = new Promise((resolve) => resolve("Promesse 2")); // 🐇 rapide
const p3 = new Promise((resolve) => resolve("Promesse 3")); // 🐕 moyenne

Promise.any([p1, p2, p3]).then((valeur) => {
  console.log(valeur); // "Promesse 2"
});

Résumé vidéo