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.
You promise?
By Volodymyr Pavlyuk
Volodymyr Pavlyuk
• Almost 10 years in software development industry
• Web UI expert at SoftServe
Facebook: www.facebook.c...
Warning!
This presentation contains programming
code.
No cats beyond this point!
The Problem
Asynchronous JavaScript
APIs
// Synchronous
var contents = readFile('file.txt');
// …becomes
readFile('file.txt', function...
Error handling is ugly
readFile('file.txt', function(err, contents) {
if (error) {
handleError();
} else {
// do something...
You can’t throw!
readFile('file.txt', function(err, contents) {
if (error) throw error; // <- no one will catch it
});
You can’t throw!
function causeException() {
something.prop; // <- this causes exception
}
try {
setTimeout(function() {
c...
Chaining
getUser("UserName", function (user) {
getBestFriend(user, function (friend) {
ui.showBestFriend(friend);
});
});
Even worse with error
handling
getUser("UserName", function (err, user) {
if (err) {
ui.error(err);
} else {
getBestFriend...
Callbacks are hell
• No return
• No throw
• No consistency in callback API’s
• No guarantees: callback can be called
once,...
Callbacks are a hack
• They are literally the simplest thing that could
work.
• But as a replacement for synchronous contr...
Any solution?
Promises/A+
Promises are the right
abstraction
Instead of calling a passed callback, return a
promise:
readFile('file.txt', function(e...
A promise is an
ASYNCHRONOU
S value
Promise guarantees
var promiseForResult = readFile(“file.txt”);
promiseForResult.then(
function onFulfilled(result) {
// P...
https://github.com/promises-
aplus/promises-spec
promiseForResult.then(onFulfilled, onRejected);
• Only one of onFulfilled...
Promises can be chained
var transformedPromise = originalPromise.then(onFulfilled,
onRejected);
• If the called handler re...
Keep The Sync ⇔ Async Parallel In
Mind
Simple Functional Transform
var user = getUser();
var userName = user.name;
// becomes
var userNamePromise = getUser().the...
Reacting with an Exception
var user = getUser();
if (user === null)
throw new Error("null user!");
//becomes
var userPromi...
Handling an Exception
try {
deliverPizzaTo(tweet, 'volopav');
} catch (error) {
handleError(error);
}
// becomes
deliverPi...
Rethrowing an Exception
try {
var user = getUser('volopav');
} catch (error) {
throw new Error('ERROR: ' + error.message);...
Chaining
getUser("volopav", function (user) {
getBestFriend(user, function (friend) {
ui.showBestFriend(friend);
});
});
/...
Promises as First-Class
Objects
Because promises are first-class objects, you can build simple
operations on them instead ...
Promise Patterns: all + spread
all([getUser(), getCompany()]).then(function (results) {
console.log("user = ", results[0])...
Promise Patterns:
try/catch/finally
ui.startSpinner();
getUser("volopav")
.then(getBestFriend)
.then(ui.showBestFriend)
.c...
Promise Patterns: map + all
var userIds = ["123", "456", "789"];
all(userIds.map(getUserById))
.then(function (users) {
co...
This is looking nice, but I don’t
have APIs which return
promises?
Choose a Library
Best implementations:
• Q, by Kris Kowal and Domenic:
https://github.com/kriskowal/q
• When.js, by Brian ...
$.Deferred
• jQuery’s $.Deferred is a very buggy attempted
implementation, that entirely misses the sync ⇔ async
parallel
...
function getUser(name) {
var defer = Q.defer();
ajax(url, {name: name}, function(err, response) {
if (err) {
defer.reject(...
Denodify
var readFile = Q.denodeify(fs.readFile);
var readDir = Q.denodeify(fs.readdir);
readDir("/tmp")
.get("0")
.then(r...
ES6 native support of
promises
http://www.html5rocks.com/en/tutorials/es6/promi
ses/
So native APIs will return promises!
Keep The Sync ⇔ Async Parallel In
Mind
• Use promises for single operations that can result in fulfillment
( returning a v...
Promises Are Not
• A replacement for events
• A replacement for streams
• A way of doing functional reactive programming
T...
Questions?
You promise?
Upcoming SlideShare
Loading in …5
×

You promise?

856 views

Published on

by Volodymyr Pavlyuk

Published in: Software
  • Be the first to comment

You promise?

  1. 1. You promise? By Volodymyr Pavlyuk
  2. 2. Volodymyr Pavlyuk • Almost 10 years in software development industry • Web UI expert at SoftServe Facebook: www.facebook.com/volopav You can even follow me on Instagram – @volopav
  3. 3. Warning! This presentation contains programming code.
  4. 4. No cats beyond this point!
  5. 5. The Problem
  6. 6. Asynchronous JavaScript APIs // Synchronous var contents = readFile('file.txt'); // …becomes readFile('file.txt', function(err, contents) { // Process result here // Note, that there is no return });
  7. 7. Error handling is ugly readFile('file.txt', function(err, contents) { if (error) { handleError(); } else { // do something with contents } });
  8. 8. You can’t throw! readFile('file.txt', function(err, contents) { if (error) throw error; // <- no one will catch it });
  9. 9. You can’t throw! function causeException() { something.prop; // <- this causes exception } try { setTimeout(function() { causeException(); }, 0); } catch (e) { console.log(e); // <- will never get here }
  10. 10. Chaining getUser("UserName", function (user) { getBestFriend(user, function (friend) { ui.showBestFriend(friend); }); });
  11. 11. Even worse with error handling getUser("UserName", function (err, user) { if (err) { ui.error(err); } else { getBestFriend(user, function (err, friend) { if (err) { ui.error(err); } else { ui.showBestFriend(friend); } }); } });
  12. 12. Callbacks are hell • No return • No throw • No consistency in callback API’s • No guarantees: callback can be called once, multiple times or not called at all
  13. 13. Callbacks are a hack • They are literally the simplest thing that could work. • But as a replacement for synchronous control flow, they suck. • We lose the flow of our code writing callbacks that tie together other callbacks.
  14. 14. Any solution? Promises/A+
  15. 15. Promises are the right abstraction Instead of calling a passed callback, return a promise: readFile('file.txt', function(err, contents) { // Process result here }); // becomes var promiseForContents = readFile("file.txt");
  16. 16. A promise is an ASYNCHRONOU S value
  17. 17. Promise guarantees var promiseForResult = readFile(“file.txt”); promiseForResult.then( function onFulfilled(result) { // Precess result }, function onRejected(reason) { // handle error } );
  18. 18. https://github.com/promises- aplus/promises-spec promiseForResult.then(onFulfilled, onRejected); • Only one of onFulfilled or onRejected will be called. • onFulfilled will be called with a single fulfillment value (⇔ return value). • onRejected will be called with a single rejection reason (⇔ thrown exception). • If the promise is already settled, the handlers will still be called once you attach them. • The handlers will always be called asynchronously.
  19. 19. Promises can be chained var transformedPromise = originalPromise.then(onFulfilled, onRejected); • If the called handler returns a value, transformedPromise will be resolved with that value: • If the returned value is a promise, we adopt its state. • Otherwise, transformedPromise is fulfilled with that value. • If the called handler throws an exception, transformedPromise will be rejected with that exception.
  20. 20. Keep The Sync ⇔ Async Parallel In Mind
  21. 21. Simple Functional Transform var user = getUser(); var userName = user.name; // becomes var userNamePromise = getUser().then(function (user) { return user.name; });
  22. 22. Reacting with an Exception var user = getUser(); if (user === null) throw new Error("null user!"); //becomes var userPromise = getUser().then(function (user) { if (user === null) throw new Error("null user!"); return user; });
  23. 23. Handling an Exception try { deliverPizzaTo(tweet, 'volopav'); } catch (error) { handleError(error); } // becomes deliverPizzaTo(tweet, 'volopav') .then(undefined, handleError)
  24. 24. Rethrowing an Exception try { var user = getUser('volopav'); } catch (error) { throw new Error('ERROR: ' + error.message); } // becomes getUser('volopav').then(undefined, function(error) { throw new Error('ERROR: ' + error.message); });
  25. 25. Chaining getUser("volopav", function (user) { getBestFriend(user, function (friend) { ui.showBestFriend(friend); }); }); // becomes getUser("volopav") .then(getBestFriend) .then(ui.showBestFriend, ui.showError)
  26. 26. Promises as First-Class Objects Because promises are first-class objects, you can build simple operations on them instead of tying callbacks together: // Fulfills with an array of results, or rejects if any reject all([getUserData(), getCompanyData()]); // Fulfills as soon as either completes, or rejects if both reject any([storeDataOnServer1(), storeDataOnServer2()]); // If writeFile accepts promises as arguments, and readFile returns one: writeFile("dest.txt", readFile("source.txt"));
  27. 27. Promise Patterns: all + spread all([getUser(), getCompany()]).then(function (results) { console.log("user = ", results[0]); console.log("company = ", results[1]); }).done(); all([getUser(), getCompany()]).spread(function (user, company) { console.log("user = ", user); console.log("company = ", company); }).done();
  28. 28. Promise Patterns: try/catch/finally ui.startSpinner(); getUser("volopav") .then(getBestFriend) .then(ui.showBestFriend) .catch(ui.error) .finally(ui.stopSpinner) .done();
  29. 29. Promise Patterns: map + all var userIds = ["123", "456", "789"]; all(userIds.map(getUserById)) .then(function (users) { console.log("all the users: ", users); }) .done();
  30. 30. This is looking nice, but I don’t have APIs which return promises?
  31. 31. Choose a Library Best implementations: • Q, by Kris Kowal and Domenic: https://github.com/kriskowal/q • When.js, by Brian Cavalier: https://github.com/cujojs/when • RSVP.js, by Yehuda Katz: https://github.com/tildeio/rsvp.js
  32. 32. $.Deferred • jQuery’s $.Deferred is a very buggy attempted implementation, that entirely misses the sync ⇔ async parallel • If you ever see a jQuery promise, kill it with fire: var realPromise = Q(jQueryPromise); var realPromise = when(jQueryPromise);
  33. 33. function getUser(name) { var defer = Q.defer(); ajax(url, {name: name}, function(err, response) { if (err) { defer.reject(err); } else { defer.resolve(response); } }); return defer.promise; }
  34. 34. Denodify var readFile = Q.denodeify(fs.readFile); var readDir = Q.denodeify(fs.readdir); readDir("/tmp") .get("0") .then(readFile) .then(function (data) { console.log("The first temporary file contains: ", data); }) .catch(function (error) { console.log("One of the steps failed: ", error); }) .done();
  35. 35. ES6 native support of promises http://www.html5rocks.com/en/tutorials/es6/promi ses/ So native APIs will return promises!
  36. 36. Keep The Sync ⇔ Async Parallel In Mind • Use promises for single operations that can result in fulfillment ( returning a value) or rejection ( throwing an exception). • If you’re ever stuck, ask “how would I structure this code if it were synchronous?” • The only exception is multiple parallel operations, which has no sync counterpart.
  37. 37. Promises Are Not • A replacement for events • A replacement for streams • A way of doing functional reactive programming They work together: • An event can trigger from one part of your UI, causing the event handler to trigger a promise-returning function • A HTTP request function can return a promise for a stream
  38. 38. Questions?

×