[ Web Proxy ]
URL:
Viewing: https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise [Back]  [Original]

Promise - JavaScript | MDN

Cette page a t traduite partir de l'anglais par la communaut. Vous pouvez contribuer en rejoignant la communaut francophone sur MDN Web Docs.

View in English Always switch to English

Promise

Baseline Large disponibilit *

Cette fonctionnalit est bien tablie et fonctionne sur de nombreux appareils et versions de navigateurs. Elle est disponible sur tous les navigateurs depuis juillet 2015.

* Certaines parties de cette fonctionnalit peuvent bnficier de prise en charge variables.

L'objet Promise (pour promesse ) est utilis pour raliser des traitements de faon asynchrone. Une promesse reprsente une valeur qui peut tre disponible maintenant, dans le futur voire jamais.

Note : Cette fonctionnalit est disponible via les Web Workers.

Pour apprendre comment fonctionnent les promesses et comment les utiliser, nous vous conseillons de commencer par l'article Utiliser les promesses du guide JavaScript.

Dans cet article

Description

L'interface Promise reprsente un intermdiaire (proxy) vers une valeur qui n'est pas ncessairement connue au moment de la cration de la promesse. Cela permet d'associer des gestionnaires au succs ventuel d'une action asynchrone et la raison d'une erreur. Ainsi, les mthodes asynchrones peuvent renvoyer des valeurs de manire similaire aux mthodes synchrones, la seule diffrence est que la valeur retourne par la mthode asynchrone est une promesse (d'avoir une valeur plus tard).

Une Promise est dans un de ces tats :

  • pending (en attente) : tat initial, la promesse n'est ni tenue, ni rompue ;
  • fulfilled (tenue) : l'opration a russi ;
  • rejected (rompue) : l'opration a chou.

Une promesse en attente peut tre tenue avec une valeur ou rompue avec une raison (erreur). Quand on arrive l'une des deux situations, les gestionnaires associs lors de l'appel de la mthode then sont alors appels. Si la promesse a dj t tenue ou rompue lorsque le gestionnaire est attach la promesse, le gestionnaire est appel. Cela permet qu'il n'y ait pas de situation de comptition entre une opration asynchrone en cours et les gestionnaires ajouts.

Les mthodes Promise.prototype.then() et Promise.prototype.catch() renvoient des promesses et peuvent ainsi tre chanes. C'est ce qu'on appelle une composition.

Schma illustrant l'enchanement des diffrents tats possibles d'une promesse et les mthodes associes [Schma illustrant l'enchanement des diffrents tats possibles d'une promesse et les mthodes associes]

Note : D'autres langages utilisent des mcanismes d'valuation la vole (lazy evaluation) et de dport des calculs (deferring computations). Ces mcanismes sont galement intituls promesses (promises). En JavaScript, les promesses correspondent des processus dj lancs et qui peuvent tre chans avec des fonctions de retour. Si vous cherchez retarder l'valuation, vous pouvez utiliser les fonctions flches sans arguments (ex. f = () => expression) afin de crer une expression valuer plus tard et utiliser f() pour l'valuer au moment voulu.

Note : On dit qu'une promesse est dans l'tat settled (acquitte) qu'elle soit tenue ou rompue mais plus en attente. Le terme resolved (rsolue) est aussi utilis concernant les promesses cela signifie que la promesse est acquitte ou bien enferme dans une chaine de promesse. Le billet de Domenic Denicola, States and fates (en anglais), contient de plus amples dtails sur la terminologie utilise.

Enchanement de promesses

Les mthodes promise.then(), promise.catch(), et promise.finally() sont utilises pour associer une action ultrieure une promesse lorsque celle-ci devient acquitte.

La mthode .then() prend deux arguments : le premier est une fonction de rappel (callback) pour le cas de rsolution de la promesse et le second argument est une fonction de rappel pour le cas d'chec. Chaque invocation de .then() renvoie une nouvelle promesse qui peut ventuellement tre utilise chane une autre promesse :

js
const maPromesse = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("toto");
  }, 300);
});

maPromesse
  .then(gestionnaireSuccesA, gestionnaireEchecA)
  .then(gestionnaireSuccesB, gestionnaireEchecB)
  .then(gestionnaireSuccesC, gestionnaireEchecC);

Le traitement continue pour chaque tape de la chane, mme lorsque .then() ne possde pas de fonction de rappel renvoyant une promesse. Ainsi, une chane d'appels peut trs bien omettre les diffrentes fonctions de rappel pour les cas d'chec jusqu'au .catch() final.

La gestion d'une promesse rompue dans chaque .then() a des consquences plus loin dans la chane de promesses. Il n'y a parfois pas le choix, car il faut grer l'erreur immdiatement. Dans de tels cas, on peut lever une erreur d'un certain type et maintenir cet tat d'erreur le long de la chane. Autrement, s'il n'est pas ncessaire d'avoir un traitement immdiat, mieux vaut laisser la gestion de l'erreur jusq'au .catch() final. Un appel .catch() peut tre vu comme un .then() qui n'a qu'une fonction de rappel pour grer les cas d'chec.

js
maPromesse
  .then(gestionnaireSuccesA)
  .then(gestionnaireSuccesB)
  .then(gestionnaireSuccesC)
  .catch(gestionnaireToutEchec);

On peut utiliser les expressions de fonctions flches pour les fonctions de rappel. Un enchanement avec cette forme pourra alors ressembler  :

js
promesse1
  .then((valeur) => {
    return valeur + " et truc";
  })
  .then((valeur) => {
    return valeur + " et truc bla";
  })
  .then((valeur) => {
    return valeur + " et blabla";
  })
  .then((valeur) => {
    return valeur + " et blabla";
  })
  .then((valeur) => {
    console.log(valeur);
  })
  .catch((err) => {
    console.log(err);
  });

La condition de terminaison d'une promesse dtermine son tat d'acquittement pour la prochaine promesse de la chane. Une promesse tenue indique un succs tandis qu'une promesse rompue indique un chec. La valeur de retour pour chaque promesse rsolue de la chane est passe la suivante avec .then(), alors que la raison de l'chec est passe au prochain gestionnaire d'chec dans la chane.

Les promesses d'une chane sont imbriques comme des poupes russes, mais le dmarrage se fait au niveau le plus imbriqu.

(promesse D, (promesse C, (promesse B, (promesse A) ) ) )

Lorsque la valeur qui suit une promesse est une autre promesse, on a un effet de remplacement dynamique. L'instruction return entrane le  dpilement  de la promesse courante et c'est la promesse suivante qui prend sa place. Pour l'exemple d'imbrication illustr avant, si l'appel .then() associ "promesse B" renvoie "promesse X", on aurait alors une situation comme celle-ci :

(promesse D, (promesse C, (promesse X) ) )

Une promesse peut tre imbrique plusieurs endroits. Dans le code qui suit, la rsolution de promesseA entranera l'appel de deux mthodes .then().

js
const promesseA = new Promise(uneFonction);
const promesseB = promesseA.then(gestionSucces1, gestionEchec1);
const promesseC = promesseA.then(gestionSucces2, gestionEchec2);

Il est possible d'affecter une action une promesse qui est dj acquitte. Dans ce cas, l'action (le cas chant), sera ralis la premire opportunit asynchrone, c'est--dire lorsque la pile d'appel aura t nettoye et qu'un battement d'horloge se sera coul. On aura autrement dit un effet similaire celui d'un setTimeout(action,10).

js
const promesseA = new Promise((resolutionFunc, rejectionFunc) => {
  resolutionFunc(777);
});
// Ici, "promesseA" est dj acquitte.
promesseA.then((val) =>
  console.log("journalisation asynchrone / val vaut :", val),
);
console.log("journalisation immdiate");

// On aura alors, dans la console, la suite de messages suivante :
// journalisation immdiate
// journalisation asynchrone / val vaut : 777

Constructeur

Promise()

Cre un nouvel objet Promise. Le constructeur est principalement utilis pour envelopper des fonctions qui ne prennent pas en charge les promesses.

Mthodes statiques

Promise.all(iterable)

Renvoie une promesse tenue lorsque toutes les promesses de l'argument itrable sont tenues ou une promesse rompue ds qu'une promesse de l'argument itrable est rompue. Si la promesse est tenue, elle est rsolue avec un tableau contenant les valeurs de rsolution des diffrentes promesses contenues dans l'itrable (dans le mme ordre que celui-ci). Si la promesse est rompue, elle contient la raison de la rupture de la part de la promesse en cause, contenue dans l'itrable. Cette mthode est utile pour agrger les rsultats de plusieurs promesses tous ensemble.

Promise.allSettled(iterable)

Attend que l'ensemble des promesses aient t acquittes (tenues ou rompues) et renvoie une promesse qui est rsolue aprs que chaque promesse ait t tenue ou rompue. La valeur de rsolution de la promesse renvoye est un tableau dont chaque lment est le rsultat des promesses initiales.

Promise.any(iterable)

Renvoie une seule promesse dont la valeur de rsolution est celle de la premire promesse rsolue de l'itrable pass en argument.

Promise.race(iterable)

Renvoie une promesse qui est tenue ou rompue ds que l'une des promesses de l'itrable est tenue ou rompue avec la valeur ou la raison correspondante.

Promise.reject(raison)

Renvoie un objet Promise qui est rompue avec la raison donne.

Promise.resolve(valeur)

Renvoie un objet Promise qui est tenue (rsolue) avec la valeur donne. Si la valeur possde une mthode then, la promesse renvoye suivra cette mthode pour arriver dans son tat, sinon la promesse renvoye sera tenue avec la valeur fournie. Gnralement, quand on veut savoir si une valeur est une promesse, on utilisera Promise.resolve(valeur) et on travaillera avec la valeur de retour en tant que promesse.

Mthodes d'instance

Promise.prototype.catch()

Ajoute une fonction de rappel comme gestionnaire d'chec la promesse et renvoie une nouvelle promesse dont la valeur de rsolution est la valeur de retour de la fonction de rappel si cette dernire est appele ou sinon la valeur de rsolution originale de la promesse si celle-ci a russi.

Promise.prototype.then()

Ajoute un gestionnaire de succs et un gestionnaire d'chec la promesse et renvoie une nouvelle promesse qui se rsout avec la valeur de retour du gestionnaire appel ou avec la valeur de rsolution originale si la promesse n'a pas t gre (dans le cas o onFulfilled ou onRejected n'est pas une fonction).

Promise.prototype.finally()

Ajoute un gestionnaire la promesse et renvoie une nouvelle promesse qui est rsolue lors de la rsolution de la premire promesse. Le gestionnaire est appel quand la premire promesse est acquitte, qu'elle ait russi ou non.

Note : Voir le guide sur les micro-tches pour en savoir plus sur la faon dont ces mthodes utilisent la queue et les services de micro-tches.

Exemples

Exemple simple

js
let maPremierePromesse = new Promise((resolve, reject) => {
  // On appelle resolve(...) lorsque notre action asynchrone
  // a russi et reject(...) lorsqu'elle a chou.
  // Dans cet exemple, on utilise setTimeout(...) pour simuler
  // du code asynchrone. En situation relle, on utiliserait
  // plutt XHR ou une API Web asynchrone.
  setTimeout(function () {
    resolve("Succs !"); // Tout s'est bien pass !
  }, 250);
});

maPremierePromesse.then((messageReussite) => {
  // messageReussite correspond  ce qui a t pass 
  // la fonction resolve(...) ci-avant.
  console.log("Youpi ! " + messageReussite);
});

Exemple avec plusieurs situations

Cet exemple illustre diffrentes techniques d'utilisation des promesses et diffrentes situations qui peuvent se produire.

En bas de l'exemple, on a une chane de promesses. Dans cet exemple, on utilise new Promise() pour la premire promesse, mais en pratique, cela proviendrait vraisemblablement d'une fonction d'une API qui renvoie une promesse.

La fonction tetheredGetNumber() illustre un gnrateur de promesse qui utilise reject() lors d'un appel asynchrone ou dans la fonction de rappel (ou dans les deux). La fonction promiseGetWord() illustre comment une fonction d'API peut gnrer et renvoyer une promesse de faon autonome.

On notera que la fonction troubleWithGetNumber() finit avec throw(). En effet, l'excution d'une chane de promesse se poursuit au travers des .then(), mme aprs une erreur, sans "throw()", l'erreur pourrait sembler traite. C'est pourquoi on voit parfois l'omission de la fonction de rappel des rejets dans les diffrents .then() et une seule fonction de rappel pour grer les checs dans le catch() final. Ici, on lve une exception avec une valeur spciale par simplicit, mais une erreur spcialise serait plus approprie.

Le code qui suit peut tre excut dans NodeJS. N'hsitez pas le manipuler et tester pour mieux comprendre comment les erreurs surviennent. Pour forcer les erreurs, vous pouvez changer la valeur de SEUIL_A.

js
"use strict";

// Pour tester la gestion d'erreur, on a un seuil
// qui provoquera des erreurs alatoirement
const SEUIL_A = 8; // Abaissez ce seuil  0 pour forcer les erreurs

function tetheredGetNumber(resolve, reject) {
  try {
    setTimeout(function () {
      const randomInt = Date.now();
      const value = randomInt % 10;
      try {
        if (value >= SEUIL_A) {
          throw new Error(`Trop grand : ${value}`);
        }
      } catch (msg) {
        reject(`Erreur dans le callback ${msg}`);
      }
      resolve(value);
      return;
    }, 500);
    // Vous pouvez exprimenter en dcommentant le 'throw'
    // qui suit
  } catch (err) {
    reject(`Erreur  l'initialisation : ${err}`);
  }
  return;
}

function determineParity(value) {
  const isOdd = value % 2 ? true : false;
  const parityInfo = { theNumber: value, isOdd: isOdd };
  return parityInfo;
}

function troubleWithGetNumber(reason) {
  console.error(`Problme pour avoir le nombre : ${reason}`);
  throw -999; // on doit utiliser throw pour maintenir l'tat d'erreur
}

function promiseGetWord(parityInfo) {
  const tetheredGetWord = function (resolve, reject) {
    const theNumber = parityInfo.theNumber;
    const seuil_B = SEUIL_A - 1;
    if (theNumber >= seuil_B) {
      reject(`Toujours trop grand : ${theNumber}`);
    } else {
      parityInfo.wordEvenOdd = parityInfo.isOdd ? "impair" : "pair";
      resolve(parityInfo);
    }
    return;
  };
  return new Promise(tetheredGetWord);
}

new Promise(tetheredGetNumber)
  .then(determineParity, troubleWithGetNumber)
  .then(promiseGetWord)
  .then((info) => {
    console.log("On a eu : ", info.theNumber, " , ", info.wordEvenOdd);
    return info;
  })
  .catch((reason) => {
    if (reason === -999) {
      console.error("Erreur prcdemment gre");
    } else {
      console.error(`Problme avec promiseGetWord(): ${reason}`);
    }
  })
  .finally((info) => console.log("C'est fini."));

Exemple interactif

Dans le court exemple qui suit, on illustre le mcanisme d'une Promise. La mthode testPromise() est appele chaque fois qu'on clique sur l'lment <button>. Cette mthode cre une promesse qui sera tenue grce la fonction setTimeout(), et avec la valeur comptePromesse (nombre commenant 1) aprs 1s 3s (alatoire). Le constructeur Promise() est utilis pour crer la promesse.

Le fait que la promesse soit tenue est simplement enregistr via un callback sur p1.then(). Quelques indicateurs illustrent la manire dont la partie synchrone est dcouple de la partie asynchrone.

HTML

html
<button id="btn" type="button">Crer un objet Promise !</button>
<div id="log"></div>

JavaScript

js
"use strict";
let comptePromesse = 0;

function testPromise() {
  let thisComptePromesse = ++comptePromesse;

  let log = document.getElementById("log");
  log.insertAdjacentHTML(
    "beforeend",
    thisComptePromesse +
      ") Started (<small>Dbut du code synchrone</small>)<br/>",
  );

  // on cre une nouvelle promesse :
  let p1 = new Promise(
    // La fonction de rsolution est appele avec la capacit de
    // tenir ou de rompre la promesse
    function (resolve, reject) {
      log.insertAdjacentHTML(
        "beforeend",
        thisComptePromesse +
          ") Promise started (<small>Dbut du code asynchrone</small>)<br/>",
      );

      // Voici un exemple simple pour crer un code asynchrone
      window.setTimeout(
        function () {
          // On tient la promesse !
          resolve(thisComptePromesse);
        },
        Math.random() * 2000 + 1000,
      );
    },
  );

  // On dfinit ce qui se passe quand la promesse est tenue
  // et ce qu'on appelle (uniquement) dans ce cas
  // La mthode catch() dfinit le traitement  effectuer
  // quand la promesse est rompue.
  p1.then(
    // On affiche un message avec la valeur
    function (val) {
      log.insertAdjacentHTML(
        "beforeend",
        val +
          ") Promise fulfilled (<small>Fin du code asynchrone</small>)<br/>",
      );
    },
  ).catch(
    // Promesse rejete
    function () {
      console.log("promesse rompue");
    },
  );

  log.insertAdjacentHTML(
    "beforeend",
    thisComptePromesse +
      ") Promise made (<small>Fin du code synchrone</small>)<br/>",
  );
}

if ("Promise" in window) {
  let btn = document.getElementById("btn");
  btn.addEventListener("click", testPromise);
} else {
  log = document.getElementById("log");
  log.innerHTML =
    "L'exemple live n'est pas disponible pour votre navigateur car celui-ci ne supporte pas l'interface <code>Promise<code>.";
}

L'exemple s'excute lorsqu'on clique sur le bouton. Pour tester cet exemple, il est ncessaire d'utiliser un navigateur qui supporte les objets Promise. En cliquant plusieurs fois sur le bouton en peu de temps, on verra qu'il y a plusieurs promesses tenues les une aprs les autres.

Charger une image en XHR

Un autre exemple simple utilisant Promise et XMLHttpRequest afin de charger une image est disponible sur le dpt GitHub MDN js-examples. Vous pouvez galement voir le rsultat. Chaque tape est commente afin de vous permettre de suivre l'tat de la promesse et l'architecture utilise avec XHR.

Spcifications

Spcification
ECMAScript 2027 LanguageSpecification
# sec-promise-objects

Compatibilit des navigateurs

Voir aussi


Web Proxy Viewer  |  New URL  |  Original Page