Async VS Promise

@AllTheDey - Gandi / Caliopen frontend developer

Disclaimer

Je n'ai pas testé le code qui va suivre (eh oui, t'as vu le ouf)

Disponible depuis ES6, supporté par tous les navigateurs récents (mais pas IE) http://devdocs.io/javascript/global_objects/promise

 

Attention au mot clé finally

 

Il n’y a pas d’opération particulière pour le faire fonctionner.

 

Babel le supporte via ses polyfill.

Promise

C’est quoi, à quoi ça sert ?

 

  • Traduction littérale : “une promesse”. (captain obviouuuuus!)
  • Permet d’attendre la fin d’une opération asynchrone.
  • Avant on avait les callbacks :

Promise

function eatAnAppleTheOldWay(apple, cb) {
  setTimeout(function () {
    var result = eat(apple);
    cb(result);
  }, 10);
}

function example() {
  eatAnAppleTheOldWay(new Apple(), (result) => {
    console.log({ result });
  });
}

Comment s’en sert-on ?

Promise

function eatAnApple(apple) {
  return new Promise((resolve, reject) => {
    setTimeout(function () {
      try {
        var result = eat(apple);
        resolve(result);
      } catch (err) {
        reject(err)
      }
    }, 10);
  });
}

function exampleA() {
  const operation = eatAnApple(new Apple());
  operation.then((resultat) => {
    console.log({ resultat });
  });
}

On peut enchainer les promesses ! (c'est dingue n'est-ce pas)

Promise

function takeACoffee() {
  throw new Error('no moar coffee');
}

function clearTheTable() {
  return 'clear the table';
}

function exampleB() {
  eatAnApple(new Apple())
    .then(() => takeACoffee())
    .then(() => clearTheTable())
    .catch((err) => alert(`Huston on a un problème : ${err}`));
}

Petite colle : décrire le comportement (bien sûr il y a un piège !)

Promise

function takeACoffee() {
  throw new Error('no moar coffee');
}

function clearTheTable() {
  return 'clear the table';
}

function exampleC() {
  eatAnApple(new Apple())
    .then(() => takeACoffee())
    .then(() => clearTheTable(), (err) => console.warn(err))
    .catch((err) => alert(`Huston on a un problème : ${err}`));
}
// -> correction

function exampleD() {
  eatAnApple(new Apple())
    .then(() => takeACoffee())
    .then(() => clearTheTable(), (err) => {
      console.warn(err);

      return Promise.reject(err);
    })
    .catch((err) => alert(`Huston on a un problème : ${err}`));
}

Pyramid of Doom (bon ok c'est esthétique)

Promise

function exampleE() {
  eatAnApple(new Apple())
    .then((r1) => {
      return takeACoffee(r1)
        .then((r2) => {
          return clearTheTable(r2)
            .then((r3) => {
              return { r1, r2, r3 };
            });
        });
    })
    .then(pyramidResults => console.log({ pyramidResults }))
    .catch((err) => alert(`Huston on a un problème : ${err}`));
}

Async/Await

Disponible dans ES2017, supporté par ... pas mal de navigateurs récents

https://devdocs.io/javascript/statements/async_function

 

Babel le supporte en utilisant le preset stage0 au moins

Async/Await

C’est quoi, à quoi ça sert ?

 

  • Déclaration de fonction asynchrone
  • Attend le résultat des opérations précédées par await
  • Avant on avait les ... (heu non rien)

Async/Await

Comment s’en sert-on ?

async function exampleF() {
  try {
    const r1 = await eatAnApple(new Apple());
    const r2 = await takeACoffee(r1);
    const r3 = await clearTheTable(r2);

    return { r1, r2, r3 };
  } catch (err) {
    console.warn(err);

    throw err;
  }
}
// équivalent

function exampleE() {
  return eatAnApple(new Apple())
    .then((r1) => {
      return takeACoffee(r1)
        .then((r2) => {
          return clearTheTable(r2)
            .then((r3) => {
              return { r1, r2, r3 };
            });
        });
    })
    .catch((err) => {
      console.warn(err);
      
      return Promise.reject(err);  
    });
}

Async/Await

Plot twist
une fonction async ça reste une promesse !

async function exampleF() {
  try {
    const r1 = await eatAnApple(new Apple());
    const r2 = await takeACoffee(r1);
    const r3 = await clearTheTable(r2);

    return { r1, r2, r3 };
  } catch (err) {
    console.warn(err);

    throw err;
  }
}


function exampleG() {
  exampleF()
    .then((results) => console.log('loul', { results }));
    .catch(err => alert(err))
}

Async/Await

Des fois, inutile de faire compliqué

async function exampleH() {
  await eatAnApple(new Apple());

  return await takeACoffee();
}
async function exampleI() {
  return await eatAnApple(new Apple());

  return takeACoffee();
}

Async/Await

Déboguer pas à pas la version transpilé

var exampleF = function () {
  var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
    var r1, r2, r3;
    return regeneratorRuntime.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            _context.prev = 0;
            _context.next = 3;
            return eatAnApple(new Apple());

          case 3:
            r1 = _context.sent;
            _context.next = 6;
            return takeACoffee(r1);

          case 6:
            r2 = _context.sent;
            _context.next = 9;
            return clearTheTable(r2);

          case 9:
            r3 = _context.sent;
            return _context.abrupt("return", { r1: r1, r2: r2, r3: r3 });

          case 13:
            _context.prev = 13;
            _context.t0 = _context["catch"](0);

            console.warn(_context.t0);

            throw _context.t0;

          case 17:
          case "end":
            return _context.stop();
        }
      }
    }, _callee, this, [[0, 13]]);
  }));

  return function exampleF() {
    return _ref.apply(this, arguments);
  };
}();

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }

And the winner is ...

No one

  • async/await ce n'est que du sucre syntaxique
  • Des fois il est préférable d'utiliser des promesses plutôt que de bloquer l’exécution
  • Les deux cohabitent sans soucis
  • Globalement async/await se lit mieux mais ne se prête pas à toutes les situations

Kthxbye

Des questions ?

Async VS Promise

By allthedey

Async VS Promise

Which one is the best ?! The code used is available on https://gist.github.com/iamdey/a5c342c74c7f0403e360bec9c3dfbdd5

  • 226