Promise

Cette fonction fait partie du standard ECMAScript 2015 (ES6)
Cette technologie a été finalisée mais il est préférable de consulter le tableau de compatibilité pour connaître l'état de l'implémentation dans les différents navigateurs.

L'objet Promise (pour « promesse ») est utilisé pour réaliser des opérations de façon asynchrone. Une promesse est dans un de ces états :

  • en attente : état initial, la promesse n'est ni remplie, ni rompue
  • tenue : l'opération a réussi
  • rompue : l'opération a échoué
  • acquittée : la promesse est tenue ou rompue mais elle n'est plus en attente.

Syntaxe

new Promise(exécuteur);
new Promise(function(resolve, reject) { ... });

Paramètres

exécuteur
Un objet fonction qui prend deux arguments : resolve et reject. Le premier argument tient la promesse et le second la rompt. Cette fonction peut être appelée une fois que l'opération est terminée.

Description

L'interface Promise représente un intermédiaire (proxy) vers une valeur qui n'est pas nécessairement connue au moment de sa création. Cela permet de gérer des actions asynchrones et de leur associer des gestionnaires d'erreur. Ainsi, des méthodes asynchrones renvoient des valeurs comme les méthodes synchrones, la seule différence est que la valeur retournée par la méthode asynchrone est une promesse (d'avoir une valeur plus tard).

Une promise peut être tenue avec une valeur ou refusée avec une raison. Quand on arrive à l'une des deux situations, les gestionnaires associés sont alors appelés. (Si la promesse a déjà été tenue ou refusée lorsque le gestionnaire est attaché à la promesse, le gestionnaire est appelé. Cela permet qu'il n'y ait pas de situation de compétition lorsqu'on attache les gestionnaires aux promesses correspondantes).

Les méthodes Promise.prototype.then et Promise.prototype.catch renvoient des promesses et peuvent ainsi être chaînées. C'est ce qu'on appelle une composition.

Propriétés

Promise.length
Une propriété de longueur qui vaut 1 (le nombre d'arguments pour le constructeur).
Promise.prototype
Cette propriété représente le prototype du constructeur Promise.

Méthodes

Promise.all(itérable)
Renvoie une promesse qui est tenue lorsque toutes les promesses de l'argument itérables sont tenues.
Promise.race(itérable)
Renvoie une promesse qui est tenue ou rompue dès que l'une des promesses de l'itérable est tenue ou rompue avec la valeur ou la raison correspondante.
Promise.reject(raison)
Renvoie un objet Promise qui est rompu avec la raison donnée.
Promise.resolve(valeur)
Renvoie un objet Promise qui est tenue (résolue) avec la valeur donnée. Si la valeur possède une méthode then, la promesse renvoyée « suivra » cette méthode pour arriver dans son état, sinon la promesse renvoyée sera tenue avec la valeur fournie. Généralement, quand on veut savoir si une valeur est une promesse, on utilisera Promise.resolve(valeur) et on travaillera avec la valeur de retour engendrée.

Prototype de Promise

Propriétés

Méthodes

Exemples

Créer un objet Promise

Dans le court exemple qui suit, on illustre le mécanisme d'une Promise. La méthode testPromise() est appelée chaque fois qu'on clique sur l'élément <button>. Cette méthode crée une promesse qui sera tenue grâce à la fonction window.setTimeout(), et avec la valeur après 1s à 3s (aléatoire).

Le fait que la promesse soit tenue est enregistré via un callback sur p1.then(). Quelques indicateurs illustrent la manière dont la partie synchrone est découplée de la partie asynchrone.

'use strict';
var comptePromesse = 0;

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

  var log = document.getElementById('log');
  log.insertAdjacentHTML('beforeend', thisComptePromesse + 
      ') Started (<small>Début du code synchrone</small>)<br/>');

  // on crée une nouvelle promesse :
  var p1 = new Promise(
    // La fonction de résolution est appelée avec la capacité de 
    // tenir ou de rompre la promesse
    function(resolve, reject) {       
      log.insertAdjacentHTML('beforeend', thisComptePromesse + 
          ') Promise started (<small>Début du code asynchrone</small>)<br/>');

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

  // On définit ce qui se passe quand la promesse est tenue
  // et ce qu'on appelle (uniquement) dans ce cas
  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 rejetée
      function() { 
        console.log("promesse rompue");
      });

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

Cet exemple s'exécute lorsqu'on clique sur le bouton. Pour tester cet exemple, il est nécessaire 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 après les autres.

Utiliser XMLHttpRequest() avec une promesse

Dans l'exemple qui suit, on illustre comment utiliser une promesse pour fournir le résultat d'une requête :

'use strict';

// A-> $http cette fonction est implémentée pour respecter le patron
// de conception (pattern) Adaptateur
function $http(url){
 
  // Un exemple d'objet
  var core = {

    // La méthode qui effectue la requête AJAX
    ajax : function (method, url, args) {

      // On établit une promesse en retour
      var promise = new Promise( function (resolve, reject) {

        // On instancie un XMLHttpRequest
        var client = new XMLHttpRequest();
        var uri = url;

        if (args && (method === 'POST' || method === 'PUT')) {
          uri += '?';
          var argcount = 0;
          for (var key in args) {
            if (args.hasOwnProperty(key)) {
              if (argcount++) {
                uri += '&';
              }
              uri += encodeURIComponent(key) + '=' + encodeURIComponent(args[key]);
            }
          }
        }

        client.open(method, uri);
        client.send();

        client.onload = function () {
          if (this.status == 200) {
            // On utilise la fonction "resolve" lorsque this.status vaut 200
            resolve(this.response);
          } else {
            // On utilise la fonction "reject" lorsque this.status est différent de 200
            reject(this.statusText);
          }
        };
        client.onerror = function () {
          reject(this.statusText);
        };
      });

      // Return the promise
      return promise;
    }
  };

  // Pattern adaptateur
  return {
    'get' : function(args) {
      return core.ajax('GET', url, args);
    },
    'post' : function(args) {
      return core.ajax('POST', url, args);
    },
    'put' : function(args) {
      return core.ajax('PUT', url, args);
    },
    'delete' : function(args) {
      return core.ajax('DELETE', url, args);
    }
  };
};
// Fin de A

// B-> Ici on définit les fonctions et les charges utiles
var mdnAPI = 'https://developer.mozilla.org/en-US/search.json';
var payload = {
  'topic' : 'js',
  'q'     : 'Promise'
};

var callback = {
  success : function(data){
     console.log(1, 'success', JSON.parse(data));
  },
  error : function(data){
     console.log(2, 'error', JSON.parse(data));
  }
};
// End B

// On exécute la méthode
$http(mdnAPI)
  .get(payload)
  .then(callback.success)
  .catch(callback.error);

// Une alternative qui appelle la méthode et permet de gérer le rejet de la promesse différemment
$http(mdnAPI) 
  .get(payload) 
  .then(callback.success, callback.error);

// Une autre alternative pour la gestion du rejet de la promesse
$http(mdnAPI) 
  .get(payload) 
  .then(callback.success)
  .then(undefined, callback.error);;

 

Charger une image en XHR

Un autre exemple simple utilisant Promise et XMLHttpRequest afin de charger une image est disponible sur le dépôt GitHub MDN promise-test. Vous pouvez également consulter le résultat obtenu sur cette page. Chaque étape est commentée afin de vous permettre de suivre l'état de la promesse et l'architecture utilisée avec XHR.

Spécifications

Spécification Statut Commentaires
ECMAScript 2015 (6th Edition, ECMA-262)
La définition de 'Promise' dans cette spécification.
Standard Définition initiale au sein d'un standard ECMA.

Compatibilité des navigateurs

Fonctionnalité Chrome Firefox (Gecko) Internet Explorer Opera Safari Edge
Support simple 32.0 29.0 (29.0) [1] Pas de support 19 7.1 (Oui)
Fonctionnalité Android Webview Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile Chrome pour Android
Support simple Pas de support (Oui) 29.0 (29.0) [1] Pas de support Pas de support 8 32.0

[1] Gecko 24 possédait une implémentation expérimentale de l'objet Promise, sous le nom Future. Le nom actuel fut utilisé dans Gecko 25, mais désactivé par défaut avec la préférence dom.promise.enabled. Le bug bug 918806 a permis d'activer les promesses par défaut avec Gecko 29.

Voir aussi

Étiquettes et contributeurs liés au document

Contributeurs à cette page : SphinxKnight, neveldo, nicodel, Goofy, teoli, riplay777
Dernière mise à jour par : SphinxKnight,