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