The Best Code is No Code At All

Un blog avec du code dedans.

Promesse de promesse, promis ?

Lors d’une conversation avec un collègue de travail (Emmanuel Demey), une question est venue :

Si une promesse prend comme argument de son resolve une promesse, que se passe t’il dans le then de la méthode appelante ?

Le resultat est une promesse ou une String ?

Le code

Version native :

var method01 = function () {
  return new Promise(function (resolve, reject) {
    console.log('start method01');

    setTimeout(function () {
      console.log('resolve method01');
      resolve('yeah');
    }, 5000);
  });
};

var method02 = function () {
  return new Promise(function (resolve, reject) {
    console.log('start method02');

    setTimeout(function () {
      console.log('resolve method02');
        resolve(method01());
    }, 1000);
  });
};

method02().then(function (data) {
    // La question : 'data' est une promesse ou une string ?
    console.log('then method2', data);
});

Version avec $q d’AngularJS :

var method01 = function () {
  console.log('start method01');

  var deferred = $q.defer();

  setTimeout(function () {
    console.log('resolve method01');
    deferred.resolve('yeah');
  }, 5000);

  return deferred.promise;
};

var method02 = function () {
  console.log('start method02');

  var deferred = $q.defer();

  setTimeout(function () {
    console.log('resolve method02');
    deferred.resolve(method01());
  }, 1000);

  return deferred.promise;
};

method02().then(function (data) {
    // La question : 'data' est une promesse ou une string ?
  console.log('then method2', data);
});

La réponse

Réponse à la question : c’est une String !

Résultat :

start method02
resolve method02
start method01
resolve method01
then method2 yeah

Pourquoi ?

Pourquoi ’then method2 yeah’ alors que method02 est résolue avant method01 ?

Dans la spécification : point-49

If x is a promise, adopt its state [3.4]:

  • If x is pending, promise must remain pending until x is fulfilled or rejected.
  • If/when x is fulfilled, fulfill promise with the same value.
  • If/when x is rejected, reject promise with the same reason.

Donc method02().then attend la resolution de la promesse retournée par method02.

Hors cette promesse ne peut être résolue (fin de l’appel de la fonction resolve) que lorsque la méthode method01 aura fini son traitement en étant résolue ou rejectée.

Pour être plus clair :

resolve(promesse);
// équivalent à
promesse.then(...)

Autres points notables

Resolve & fonction

Il n’est pas possible de retourner une fonction en tant que promesse : si une fonction est passée dans le resolve, elle interprétée comme un thenable function(resolve, reject) {...}.

Voir la spécification : point-56

Funny callback

var method01 = function () {
  return new Promise(function (resolve, reject) {
    console.log('start method01');

    setTimeout(function () {
      console.log('resolve method01');
      resolve('yeah');
    }, 5000);
  });
};

method01.then(console.log); // Callback
comments powered by Disqus