you promise?

39
You promise? By Volodymyr Pavlyuk

Upload: it-weekend

Post on 10-May-2015

328 views

Category:

Software


6 download

DESCRIPTION

by Volodymyr Pavlyuk

TRANSCRIPT

Page 1: You promise?

You promise?

By Volodymyr Pavlyuk

Page 2: You promise?

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

Page 3: You promise?

Warning!This presentation contains

programming code.

Page 4: You promise?

No cats beyond this point!

Page 5: You promise?

The Problem

Page 6: You promise?
Page 7: You promise?

Asynchronous JavaScript APIs

// Synchronous var contents = readFile('file.txt');

// …becomesreadFile('file.txt', function(err, contents) {

// Process result here // Note, that there is no return});

Page 8: You promise?

Error handling is ugly

readFile('file.txt', function(err, contents) {if (error) {handleError();

} else {// do something with contents

}});

Page 9: You promise?

You can’t throw!

readFile('file.txt', function(err, contents) {if (error) throw error; // <- no one will catch it

});

Page 10: You promise?

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

}

Page 11: You promise?

Chaining

getUser("UserName", function (user) {getBestFriend(user, function (friend) {

ui.showBestFriend(friend);});

});

Page 12: You promise?

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);}

});}

});

Page 13: You promise?

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

Page 14: You promise?

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.

Page 15: You promise?

Any solution?

Promises/A+

Page 16: You promise?

Promises are the right abstraction

Instead of calling a passed callback, return a promise:

readFile('file.txt', function(err, contents) {// Process result here

});

// becomesvar promiseForContents = readFile("file.txt");

Page 17: You promise?

A promise is an

ASYNCHRONOUS value

Page 18: You promise?

Promise guarantees

var promiseForResult = readFile(“file.txt”);

promiseForResult.then(function onFulfilled(result) {

// Precess result},function onRejected(reason) {

// handle error}

);

Page 19: You promise?

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.

Page 20: You promise?

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.

Page 21: You promise?

Keep The Sync ⇔ Async Parallel In Mind

Page 22: You promise?

Simple Functional Transform

var user = getUser();var userName = user.name;

// becomes

var userNamePromise = getUser().then(function (user) {

return user.name;});

Page 23: You promise?

Reacting with an Exception

var user = getUser();if (user === null)

throw new Error("null user!");

//becomesvar userPromise = getUser().then(function (user) {

if (user === null)throw new Error("null user!");

return user;});

Page 24: You promise?

Handling an Exception

try { deliverPizzaTo(tweet, 'volopav');

} catch (error) { handleError(error);

}

// becomesdeliverPizzaTo(tweet, 'volopav')

.then(undefined, handleError)

Page 25: You promise?

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);});

Page 26: You promise?

Chaining

getUser("volopav", function (user) { getBestFriend(user, function (friend) {

ui.showBestFriend(friend); });

});

// becomesgetUser("volopav")

.then(getBestFriend) .then(ui.showBestFriend, ui.showError)

Page 27: You promise?

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 rejectall([getUserData(), getCompanyData()]);

// Fulfills as soon as either completes, or rejects if both rejectany([storeDataOnServer1(), storeDataOnServer2()]);

// If writeFile accepts promises as arguments, and readFile returns one:writeFile("dest.txt", readFile("source.txt"));

Page 28: You promise?

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();

Page 29: You promise?

Promise Patterns: try/catch/finally

ui.startSpinner();getUser("volopav")

.then(getBestFriend)

.then(ui.showBestFriend)

.catch(ui.error)

.finally(ui.stopSpinner)

.done();

Page 30: You promise?

Promise Patterns: map + all

var userIds = ["123", "456", "789"];

all(userIds.map(getUserById)) .then(function (users) {

console.log("all the users: ", users); }) .done();

Page 31: You promise?

This is looking nice, but I don’t have APIs which

return promises?

Page 32: You promise?

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

Page 33: You promise?

$.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);

Page 34: You promise?

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;}

Page 35: You promise?

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();

Page 36: You promise?

ES6 native support of promises

http://www.html5rocks.com/en/tutorials/es6/promises/

So native APIs will return promises!

Page 37: You promise?

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.

Page 38: You promise?

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

Page 39: You promise?

Questions?