Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Promise is a Promise

109 views

Published on

These slides have been presented in a lecture about promises at the Front Clouders meetup on on May 28th 2019.

Author: Mateusz Bryła (https://www.linkedin.com/in/mateusz-bryła-78aa1572/)
Dreamer, programmer, consultant, trainer. Founder at Lingmates, Team Lead at Codete.

Published in: Software
  • Be the first to comment

Promise is a Promise

  1. 1. By Mateusz Bryła Promise((resolve, reject) => { Math.random() > 0.5 ? resolve(love()) : reject(hate()); }).then(love => marry()).catch(hate => moveToAlaska());
  2. 2. Let’s talk about JavaScript... https://www.destroyallsoftware.com/talks/wat ;)
  3. 3. What are we even talking about? Promise Objects Introduced: ECMAScript 2015 (previously ES6) - June 2015 Spec: https://www.ecma-international.org/ecma-262/6.0/#sec-promise-objects Support: https://caniuse.com/#feat=promises Polyfills: - https://github.com/stefanpenner/es6-promise - http://bluebirdjs.com/docs/install.html Async / Await Introduced: ECMAScript 2017 - June 2017 Spec: https://www.ecma-international.org/ecma-262/8.0/#sec-async-function-definitions
  4. 4. What are we even talking about? Promise Objects Introduced: ECMAScript 2015 (previously ES6) - June 2015 Spec: https://www.ecma-international.org/ecma-262/6.0/#sec-promise-objects Support: https://caniuse.com/#feat=promises
  5. 5. What are we even talking about? Promise Objects Introduced: ECMAScript 2015 (previously ES6) - June 2015 Spec: https://www.ecma-international.org/ecma-262/6.0/#sec-promise-objects Support: https://caniuse.com/#feat=promises
  6. 6. What are we even talking about? Promise Objects Introduced: ECMAScript 2015 (previously ES6) - June 2015 Spec: https://www.ecma-international.org/ecma-262/6.0/#sec-promise-objects Support: https://caniuse.com/#feat=promises
  7. 7. What are we even talking about? Promise Objects Introduced: ECMAScript 2015 (previously ES6) - June 2015 Spec: https://www.ecma-international.org/ecma-262/6.0/#sec-promise-objects Support: https://caniuse.com/#feat=promises Polyfills: - https://github.com/stefanpenner/es6-promise - http://bluebirdjs.com/docs/install.html
  8. 8. What are we even talking about? Promise Objects Introduced: ECMAScript 2015 (previously ES6) - June 2015 Spec: https://www.ecma-international.org/ecma-262/6.0/#sec-promise-objects Support: https://caniuse.com/#feat=promises Polyfills: - https://github.com/stefanpenner/es6-promise - http://bluebirdjs.com/docs/install.html Async / Await Introduced: ECMAScript 2017 - June 2017 Spec: https://www.ecma-international.org/ecma-262/8.0/#sec-async-function-definitions Support: https://caniuse.com/#feat=async-functions
  9. 9. What are we even talking about? Promise Objects Introduced: ECMAScript 2015 (previously ES6) - June 2015 Spec: https://www.ecma-international.org/ecma-262/6.0/#sec-promise-objects Support: https://caniuse.com/#feat=promises Polyfills: - https://github.com/stefanpenner/es6-promise - http://bluebirdjs.com/docs/install.html Async / Await Introduced: ECMAScript 2017 - June 2017 Spec: https://www.ecma-international.org/ecma-262/8.0/#sec-async-function-definitions Support: https://caniuse.com/#feat=async-functions
  10. 10. Promise “An object that is used as a placeholder for the eventual results of a deferred (and possibly asynchronous) computation” Promise p state is: - fulfilled if p.then(f,r) enqueues a job to call f - rejected if p.then(f,r) enqueues a job to call r - pending if not fulfilled not rejected - settled if not pending - resolved if settled or locked in to match state of a different promise
  11. 11. function executeDelayed(operation, callback) { setTimeout(() => { try { const result = operation(); callback(null, result); } catch (error) { callback(error); } }, 1000); }
  12. 12. function executeDelayed(operation, callback) { setTimeout(() => { try { const result = operation(); callback(null, result); } catch (error) { callback(error); } }, 1000); } executeDelayed(() => { return 42; }, (error, result) => { if (error) { console.log('delayed error', error); } else { console.error('delayed result', result); } });
  13. 13. const promise = new Promise((resolve, reject) => { // perform action, call resolve / reject upon completion / error }); promise.then((result) => { // listen for completion }); promise.catch((error) => { // listen for error }); promise.finally(() => { // cleanup });
  14. 14. function executeDelayed(operation, callback) { setTimeout(() => { try { const result = operation(); callback(null, result); } catch (error) { callback(error); } }, 1000); } function executeDelayed(operation) { return new Promise((resolve, reject) => { setTimeout(() => { try { const result = operation(); resolve(result); } catch (error) { reject(error); } }, 1000); }); }
  15. 15. function executeDelayed(operation, callback) { setTimeout(() => { try { const result = operation(); callback(null, result); } catch (error) { callback(error); } }, 1000); } executeDelayed(() => { return 42; }, (error, result) => { if (error) { console.log('delayed error', error); } else { console.error('delayed result', result); } }); function executeDelayed(operation) { return new Promise((resolve, reject) => { setTimeout(() => { try { const result = operation(); resolve(result); } catch (error) { reject(error); } }, 1000); }); } executeDelayed(() => { return 42; }).then((result) => { console.log('delayed result, result); }).catch((error) => { console.error('delayed error', error); });
  16. 16. function log() { console.log(...arguments); }
  17. 17. p = new Promise((resolve, reject) => { resolve(10); }).then(x => log(x));
  18. 18. p = new Promise((resolve, reject) => { resolve(10); }).then(x => log(x)); // 10
  19. 19. p = new Promise((resolve, reject) => { reject(10); }).catch(x => log(x));
  20. 20. p = new Promise((resolve, reject) => { reject(10); }).catch(x => log(x)); // 10
  21. 21. p = new Promise((resolve, reject) => { resolve(10); resolve(20); }).then(x => log(x));
  22. 22. p = new Promise((resolve, reject) => { resolve(10); resolve(20); }).then(x => log(x)); // 10
  23. 23. p = new Promise((resolve, reject) => { resolve(10); reject(20); }).then(x => log('F', x)).catch(x => log('R', x));
  24. 24. p = new Promise((resolve, reject) => { resolve(10); reject(20); }).then(x => log('F', x)).catch(x => log('R', x)); // 10
  25. 25. p = new Promise((resolve, reject) => { reject(20); resolve(10); }).then(x => log('F', x)).catch(x => log('R', x));
  26. 26. p = new Promise((resolve, reject) => { reject(20); resolve(10); }).then(x => log('F', x)).catch(x => log('R', x)); // 20
  27. 27. const promise = new Promise((resolve, reject) => { // perform action, call resolve / reject upon completion / error }); promise.then((result) => { // listen for completion }); promise.catch((error) => { // listen for error }); promise.finally(() => { // cleanup });
  28. 28. Promise.resolve(10); new Promise((resolve) => { resolve(10); }); Promise.reject(10); new Promise((resolve, reject) => { reject(10); }); // fulfills if all fulfilled, rejected otherwise Promise.all([Promise.resolve(10), Promise.reject(10)]); // resolves as first resolves Promise.race([Promise.resolve(10), Promise.reject(10)]);
  29. 29. Promise.resolve(10) .then(x => log(x)) .then(x => log(x)) .then(x => log(x));
  30. 30. Promise.resolve(10) .then(x => log(x)) .then(x => log(x)) .then(x => log(x)); // 10 undefined undefined
  31. 31. p = Promise.resolve(10); p.then(x => log(x)); p.then(x => log(x)); p.then(x => log(x));
  32. 32. p = Promise.resolve(10); p.then(x => log(x)); p.then(x => log(x)); p.then(x => log(x)); // 10 10 10
  33. 33. Promise.resolve(10) .then(x => { log(x); return 20; }) .then(x => { log(x); return 30; }) .then(x => { log(x); });
  34. 34. Promise.resolve(10) .then(x => { log(x); return 20; }) .then(x => { log(x); return 30; }) .then(x => { log(x); }); // 10 20 30
  35. 35. Promise.resolve(10) .then(x => { log(x); return 20; }) .catch(x => { log(x); return 30; }) .then(x => { log(x); return 40; }) .then(x => { log(x); return 50; });
  36. 36. Promise.resolve(10) .then(x => { log(x); return 20; }) .catch(x => { log(x); return 30; }) .then(x => { log(x); return 40; }) .then(x => { log(x); return 50; }); // 10 20 40
  37. 37. Promise.reject(10) .catch(x => log(x)) .catch(x => log(x)) .catch(x => log(x));
  38. 38. Promise.reject(10) .catch(x => log(x)) .catch(x => log(x)) .catch(x => log(x)); // 10
  39. 39. Promise.reject(10) .catch(x => { log(x); return 20; }) .then(x => { log(x); return 30; }) .catch(x => { log(x); return 40; }) .then(x => { log(x); return 50; });
  40. 40. Promise.reject(10) .catch(x => { log(x); return 20; }) .then(x => { log(x); return 30; }) .catch(x => { log(x); return 40; }) .then(x => { log(x); return 50; }); // 10 20 30
  41. 41. Promise.resolve(10) .then(x => { log(x); return 20; }) .then(x => { log(x); throw new Error(30); }) .then(x => { log(x); return 40; }) .catch(x => { log(x); return 50; });
  42. 42. Promise.resolve(10) .then(x => { log(x); return 20; }) .then(x => { log(x); throw new Error(30); }) .then(x => { log(x); return 40; }) .catch(x => { log(x); return 50; }); // 10 20 Error(30)
  43. 43. reject(new Error(10))
  44. 44. Promise.resolve(10) .then(x => { log(x); return Promise.resolve(20); }) .then(x => { log(x); });
  45. 45. Promise.resolve(10) .then(x => { log(x); return Promise.resolve(20); }) .then(x => { log(x); }); // 10 20
  46. 46. Promise.resolve(10) .then(x => { log(x); return Promise.reject(new Error(20)); }) .then(x => { log('F', x); return 30; }) .catch(x => { log('R', x); return 40; }) .then(x => { log(x); });
  47. 47. Promise.resolve(10) .then(x => { log(x); return Promise.reject(new Error(20)); }) .then(x => { log('F', x); return 30; }) .catch(x => { log('R', x); return 40; }) .then(x => { log(x); }); // 10 R Error: 20 40
  48. 48. fetch('https://api.com/users/42') .then(response => response.json()) .then(user => fetch(`https://api.github.com/users/${user.name}`)) .then(response => response.json()) .then(user => new Promise((resolve, reject) => { // check out users projects resolve(); }));
  49. 49. Promise.all([ Promise.resolve(10), 20, Promise.resolve(30), ]);
  50. 50. Promise.all([ Promise.resolve(10), 20, Promise.resolve(30), ]); // 10 20 30
  51. 51. const token = 'secret'; Promise.all([ fetch(`https://service-a.com/profile?token=${token}`) .then(response => response.json()) .then(user => user.admin), fetch(`https://service-b.com/profile?token=${token}`) .then(response => response.json()) .then(user => user.admin), fetch(`https://service-c.com/profile?token=${token}`) .then(response => response.json()) .then(user => user.admin); ]);
  52. 52. const token = 'secret'; Promise.all([ fetch(`https://service-a.com/profile?token=${token}`) .then(response => response.json()).then(user => user.admin) .catch(error => { if (/**/) { return false; }}); fetch(`https://service-b.com/profile?token=${token}`) .then(response => response.json()).then(user => user.admin) .catch(error => { if (/**/) { return false; }}); fetch(`https://service-c.com/profile?token=${token}`) .then(response => response.json()).then(user => user.admin) .catch(error => { if (/**/) { return false; }}); ]);
  53. 53. promises keep state be mindful of promises chaining catch returns fulfilled promise if error not rethrown
  54. 54. Promise.resolve(10).then(x => { log(x); return 20; }).then(x => log(x)); Promise.resolve(30).then(x => { log(x); return 40; }).then(x => log(x));
  55. 55. Promise.resolve(10).then(x => { log(x); return 20; }).then(x => log(x)); Promise.resolve(30).then(x => { log(x); return 40; }).then(x => log(x)); // 10 30 20 40
  56. 56. Promise.resolve(10).then(x => { log(x); return Promise.resolve(20); }).then(x => log(x)); Promise.resolve(30).then(x => { log(x); return 40; }).then(x => log(x));
  57. 57. Promise.resolve(10).then(x => { log(x); return Promise.resolve(20); }).then(x => log(x)); Promise.resolve(30).then(x => { log(x); return 40; }).then(x => log(x)); // 10 30 40 20
  58. 58. setTimeout(() => log('macro'), 0); Promise.resolve().then(() => log('micro')); log('current');
  59. 59. setTimeout(() => log('macro'), 0); Promise.resolve().then(() => log('micro')); log('current'); // current micro macro
  60. 60. Promise.resolve() .then(() => { setTimeout(() => log('timeout'), 0); }) .then(() => { log('promise'); });
  61. 61. Promise.resolve() .then(() => { setTimeout(() => log('timeout'), 0); }) .then(() => { log('promise'); }); // promise timeout
  62. 62. Promise.reject(new Error(10)); VM7904:1 Uncaught (in promise) Error: 10 at <anonymous>:1:16 try { Promise.reject(new Error(10)); } catch (error) { console.log('caught error'); // will not be logged } VM7997:2 Uncaught (in promise) Error: 10 at <anonymous>:2:20
  63. 63. window.addEventListener('unhandledrejection', (event) => { console.log('unhandled', event.reason); }); p = new Promise(() => { throw new Error(20); }); // unhandled Error: 20
  64. 64. window.addEventListener('unhandledrejection', (event) => { console.log('unhandled', event.reason); }); p = new Promise(() => { throw new Error(20); }); setTimeout(() => { p.catch(e => console.log('handling', e)); }, 1000); // unhandled Error 20 // handling Error 20
  65. 65. window.addEventListener('unhandledrejection', (event) => { console.log('unhandled', event.reason); }); window.addEventListener('rejectionhandled', (event) => { console.log('handled rejected', event.reason); }); p = new Promise(() => { throw new Error(20); }); setTimeout(() => { console.log('will handle'); p.catch(e => console.log('handling', e)); console.log('handled'); }, 1000);
  66. 66. async function foo() { return 1; } foo().then(x => log(x)); // 1 async function foo() { return Promise.resolve(1); } foo().then(x => log(x)); // 1
  67. 67. p = new Promise((reject) => { setTimeout(() => { resolve(42); }. 1000); }) async function foo() { log('before'); const result = await p(); log('after', result); } // before after 42
  68. 68. (async () => { setTimeout(() => alert('timeout'), 0); await f(); alert('after await'); })();
  69. 69. (async () => { setTimeout(() => alert('timeout'), 0); await f(); alert('after await'); })(); // after await timeout
  70. 70. async function prepareDinner(meatType = 'fish') { const dinner = await prepareBaseDinner(); const meat = await selectMeat(meatType); const wine = await selectWine(meat.getWineType()); dinner.addMeat(meat); dinner.addWine(wine); return dinner; }
  71. 71. async function prepareDinner(meatType = 'fish') { const dinner = await prepareBaseDinner(); const meat = await selectMeat(meatType); const wine = await selectWine(meat.getWineType()); dinner.addMeat(meat); dinner.addWine(wine); return dinner; } // |-------dinner------->|---meat--->|---wine--->|
  72. 72. function prepareDinner(meatType = 'fish') { const dinnerPromise = prepareBaseDinner(); const meatPromise = selectMeat(meatType); const winePromise = meatPromise.then(meat => { return selectWine(meat.getWineType()); }); return Promise.all([ dinnerPromise, meatPromise, winePromise ]).then( ([ dinner, meat, wine ]) => { dinner.addMeat(meat); dinner.addWine(wine); return dinner; } ); }
  73. 73. function prepareDinner(meatType = 'fish') { const dinnerPromise = prepareBaseDinner(); const meatPromise = selectMeat(meatType); const winePromise = meatPromise.then(meat => { return selectWine(meat.getWineType()); }); return Promise.all([ dinnerPromise, meatPromise, winePromise ]).then( ([ dinner, meat, wine ]) => { dinner.addMeat(meat); dinner.addWine(wine); return dinner; } ); } // |-------dinner------->| // |---meat--->|---wine--->|
  74. 74. microtasks have priority over macrotasks unhandled rejection can be monitored mind handling unhandled rejections async uses the same microtasks queue async can execute synchronous code if not used correctly
  75. 75. Q & A
  76. 76. For bedtime readers Explanation of promises and async/await with examples and problems to solve https://javascript.info/async Async/await performance caveats: https://medium.com/@bluepnume/even-with-async-await-you-probably-still-need-p romises-9b259854c161
  77. 77. THANK YOU Mateusz Bryła

×