Promesse en JavaScript

Qu'est-ce qu'une promesse ?

Une promesse en JavaScript est un objet qui nous permet d'obtenir les résultats d'une opération asynchrone lorsque ces résultats ne sont pas immédiatement disponibles. Dans un environnement où JavaScript s'exécute de manière non-bloquante, les promesses s'avèrent essentielles lorsque nous devons attendre qu'une opération asynchrone se termine sans interrompre l'exécution du reste du programme. Parmi les cas d'utilisation fréquents des promesses, on trouve l'interaction avec des API ou le téléchargement d'images.

Les états d'une promesse

Les promesses conviennent parfaitement pour gérer des opérations asynchrones en JavaScript et se caractérisent par trois états distincts :

  1. En attente (Pending) : La promesse n’a pas encore été résolue ou rejetée.
  2. Remplie (Fulfilled) : Les opérations asynchrones sont complètes et une valeur a été retournée.
  3. Rejetée (Rejected) : Les opérations asynchrones ont échoué à un moment donné.

Syntaxe des promesses

Un objet Promise est créé par une fonction qui prend en paramètres deux fonctions, resolve et reject :

let maPromesse = new Promise((resolve, reject) => {
  // Code de la promesse ici
});

Lorsque maPromesse réussit, la fonction resolve() est appelée. En revanche, si une erreur se produit, par exemple, à cause de données invalides ou d'une erreur serveurs, alors c'est la fonction reject() qui sera exécutée.

Chaînage des promesses

Le chaînage est une technique qui permet de réaliser des opérations supplémentaires sur une promesse « remplie ». Les méthodes suivantes sont souvent utilisées pour le chaînage :

  • .then() : effectue des opérations sur un objet Promise rempli et renvoie une nouvelle valeur.
  • .catch() : gère les rejets de promesses et lance une erreur.
  • .finally() : s'exécute quelle que soit l'issue de la promesse, qu'elle soit remplie ou rejetée.

Voici un exemple illustrant l'utilisation du chaînage pour afficher un message de succès après que la promesse ait été remplie :

const promesse = new Promise((resolve, reject) => {
  const terme1 = 2;
  const terme2 = 2;
  const expression = terme1 + terme2;
  const reponse = 4;
  const expressionEstCorrecte = expression === reponse;

  // 2 + 2 = 4, donc c'est vrai !
  if (expressionEstCorrecte) {
    resolve('La promesse a été remplie !');
  } else {
    reject({
      errorType: 'ArithmeticError',
      message: "L'expression n'a pas été évaluée correctement.",
      originalExpression: `${terme1} + ${terme2} === ${reponse}`,
    });
  }
});

promesse
  .then((message) => {
    console.log(`Succès : ${message}`);
  })
  .catch((err) => {
    console.log(`${err.errorType} : ${err.message} \nExpression originale : ${err.originalExpression}`);
  })
  .finally(() => {
    console.log('Opérations terminées');
  });
// Sortie : Succès : La promesse a été remplie !

Async/Await dans les promesses

Depuis ES2017, JavaScript a introduit les mots-clés async et await, qui permettent d'écrire des promesses de manière plus lisible. Cela constitue une alternative plus concise aux autres méthodes, comme le chaînage de promesses.

Remarque : await ne peut être utilisé qu'à l'intérieur d'une fonction asynchrone, sinon une erreur de syntaxe sera générée.

function maPromesse() {
  return new Promise((resolve) => {
    resolve('Promesse réussie !');
  });
}

async function uneFonctionAsync() {
  try {
    const resultat = await maPromesse();
    console.log(resultat);
  } catch (error) {
    console.log(`Erreur de la fonction async : ${error}`);
  }
}

uneFonctionAsync();
// Sortie : Promesse réussie !

Fonctions supplémentaires avec Promise

D'autres méthodes courantes incluent : - Promise.all() : retourne une nouvelle promesse qui résout un tableau des valeurs résolues des promesses remplies. - Promise.allSettled() : retourne une promesse qui résout un tableau après que toutes les promesses dans un itérable aient été résolues ou rejetées. - Promise.race() : retourne la première promesse qui se résout ou se rejette.