var input = //...
try {
var result = computeResult(input);
displayResult(result);
} catch(e) {
displayError(e);
}
http://www.flickr.com/photos/zanehollingsworth/5701745474
computeResult(input, function(e, result) {
if(e) {
displayError(e);
} else {
displayResult(result);
}
});
computeResult(input, function(e, result) {
if(e) {
displayError(e);
} else {
try {
displayResult(result);
} catch(e) {
displayError(e);
}
}
});
function getTheResult() {
try {
return thisMightFail();
} catch(e) {
return recoverFromFailure(e);
} finally {
alwaysCleanup();
}
}
function getTheResult(nodeCallback) {
thisMightFail(function(error, result) {
if(error) {
try {
result = recoverFromFailure(error);
error = null;
} catch(e) {
error = e;
}
}
alwaysCleanup();
// If error is still falsey, we've succeeded
nodeCallback(error, result);
});
}
function getTheResult(onSuccess, onFailure) {
thisMightFail(
function(result) {
try {
onSuccess(result);
} catch(e) {
onFailure(e);
} finally {
alwaysCleanup();
}
},
function(error) {
var recoveryResult;
try {
recoveryResult = recoverFromFailure(error);
error = null;
} catch(e) {
error = e;
}
try {
alwaysCleanup();
} catch(e) {
error = e;
}
if(error) {
onFailure(error);
} else {
onSuccess(recoveryResult);
}
}
);
}
http://www.flickr.com/photos/timsnell/7986996932
- Impossible to reason about and maintain
- Recreate flow control and error handling machinery
Promises give you async versions of return
and throw
.
They let you take back the call stack.
computeResult(input)
.then(displayResult)
.otherwise(displayError);
http://know.cujojs.com/tutorials/async/mastering-async-error-handling-with-promises
function getTheResult() {
return thisMightFail()
.otherwise(recoverFromFailure);
.ensure(alwaysCleanup);
}
http://know.cujojs.com/tutorials/async/mastering-async-error-handling-with-promises
- MultiLisp, Act 1, Prolog concurrent logic variables, Joule and E promises,
java.util.concurrent.Future
, Python Twisted deferred, DojoDeferred
, F#Async<T>
, .NETTask<T>
, C++11std::future
andstd::promise
, DartFuture<T>
, ScalaFuture
- Javascript Promises/A+
http://www.flickr.com/photos/rooners/4415074931
var when = require('when');
when.reduce(
when.map($.get('/users'), getTags), groupTags)
.then(displayTags);
var nodefn = require('when/node/function');
var fs = require('fs');
var readFile = nodefn.lift(fs.readFile);
var writeFile = nodefn.lift(fs.writeFile);
// This all happens async:
writeFile('out.txt', readFile('in.txt'));
function* someNumbers() {
yield 1;
yield 2;
yield 3;
}
var iterator = someNumbers();
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { done: true }
// thisMightFail, recoverFromFailure, and
// alwaysCleanup are ASYNC!
var zomg = promisedGenerator(function* () {
var result;
try {
result = yield thisMightFail();
} catch(e) {
result = yield recoverFromFailure(e);
} finally {
yield alwaysCleanup();
}
yield result;
});
var result = zomg();
// ES5 (and ES3)
Users.get('brian')
.then(function(user) {
return user.fetchBlogPosts();
})
.then(function(posts) {
return posts.toHtml();
})
.then(function(html) {
container.innerHTML = html;
});
// ES6
container.innerHTML = yield Users.brian.posts.toHtml();
http://www.flickr.com/photos/rooners/4652345494
- VMs/platforms aren't promise-aware
- disjoint or missing stack traces
- when.js and Q can trap and report unhandled rejections
- and stitch stack traces
return
something!!- Don't break the chain
- rejection handlers work like
catch
, if you don't "rethrow", the error is considered "handled" and won't propagate- This consistency is a good thing
// You sly dog:
// If doSomething fails, no one will ever know
promise.then(doSomething);
return promise;
// You probably meant:
return promise.then(doSomething);
// Oops, you returned `undefined` which
// turns this rejection into a success
return promise.otherwise(function(e) {
logError(e);
});
// Preferably, let the error be handled higher
// in the call stack, like exceptions!
return promise;
// But if you must:
return promise.otherwise(function(e) {
logError(e);
throw e;
});
http://www.flickr.com/photos/pelegrino/6884873348
- Exposition
- Inciting incident
- Rising action
- Climax
http://wiki.commonjs.org/wiki/Promises/A
https://github.com/jquery/jquery/commit/a41f2406748e3113751ab1e5b5d990d9144123fc
https://gist.github.com/domenic/3889970
https://github.com/domenic/promise-tests
https://gist.github.com/briancavalier/eb5fc157825a170c9957
https://github.com/promises-aplus/promises-tests
- 33 verified implementations, more every week
- Several "inspired by Promises/A+" in other languages
http://dom.spec.whatwg.org/#promises
- Plot
- Character
- Theme
- Diction
- Music & spectacle (setting)
http://yehudakatz.com/2013/05/21/extend-the-web-forward/
SpringJS @ Pivotal
cujoJS co-founder
promisesaplus.com co-editor
- Promises/A+ contributors and community
- Boom, Promises/A+ was born Domenic Denicola @ JSConf US 2013