It's worth noting we are very close to finishing up a 1.1 revision of the spec, which clarifies a few things mainly around how promise libraries interoperate with each other's promises. You can find the work in our master branch (as opposed to gh-pages):
We were hoping to do a revision of the website's look at the time of the 1.1 release as well, mainly adding links to additional resources in the repository (like the implementations list, credits, etc.). A bit sad that we haven't moved fast enough to finish that before making the front page of Hacker News!
I have just started doing development in Node.js. Originally using the excellent caolan/async library (https://github.com/caolan/async) for handling synchronous situations. Now started moving towards Promises but finding it quite hard to locate any "Promises for Dummies" type guide. Most of the libraries like "q" etc (https://github.com/kriskowal/q) just give you a list of functions to use and related syntax but I have yet to come across a guide that goes into detail as to exactly how and why you use certain functions.
I am kind of figuring things out as I go along but if anyone here can point me to such guides, I would be most grateful.
Otherwise, in the Q readme we try for a "graduated tutorial" approach; would welcome any feedback you have to make it more friendly. We try to relegate the "list of functions" to the API reference at https://github.com/kriskowal/q/wiki/API-Reference
James Coglan did a good introduction of promises on his Callbacks are imperative, promises are functional: Node’s biggest missed opportunity[1] (HN discussion here[2]).
The author of Promises/A+ also wrote a nice blost post on his You're Missing the Point of Promises [3]
Promises are actually a part of a of a very well understood programming mechanism that involves Futures and Deferred as well[4]
I recently wrote two Node.js libraries that use promises extensively, an Active Record style ORM http://bookshelfjs.org and Query Builder http://knexjs.org. I actually didn't find a need for many of the higher level functions, outside of .then I'd typically stick to .all, .reject / .resolve, and occasionally .defer.
The source should be fairly annotated and is structured similar to Backbone.js, so it might be useful to take a look through and see where/how those functions are being used.
The thing about promises is their real power comes when you return them out of functions you run, thus causing any function to become async, and the promise being returned allows it to be used in a variety of ways:
promisesFunc().done(function(){ // execute on completion }
q.when(promisesFunc).then( function(){ // do stuff } )
It's nice to be able to treat something that is inherently asynchronous like it is inherently asynchronous. Feels good man.jpg. And just wait til you start mixing in generators (well, eventually).
My beef with JS Promises (uppercase "P") is that, as a programming idiom, I prefer once I have X, Y and Z, do something with X, Y and Z over get X, then get Y, then get Z. In the former case, the provisioning logic is a separate concern; it could be done in parallel, serially, or via some combination of both. In the latter case, it's inherently serial.
I wrote an alternate implementation of promises in JS (lowercase "p") that uses the former approach: https://github.com/greim/await.js
It's absolutely possible to do multiple things in parallel using Promises/A(+) then "resolve" a new promise once they're all done. That's what Q.all() in the Q library does, for example.
That API isn't written into the Promises/A+ spec because it doesn't need to be. That spec is the minimal things necessary for multiple promise implementations to be interoperable.
Personally, that sounds like a really odd complaint to make. After all, running promises in parallel should be just a matter of using a simple library function that you can very easily code yourself if its not already provided.
I tend to find that the biggest problem with promise libraries is writing code with lots of jumps and more advanced control flow. If you are using an explicit continuation-based approach then doing a jump (for a loop or for breaking out early) is just a matter of calling the appropriate continuation. On the other hand, promises naturally tend to prefer the sort of code where there is only a single return statement at the end (unless you abuse the error handling system but there are all sort of problems if you do that)
I don't understand your comment (or this is related to the lack of good introductory material noted in another comment).
You can retrieve the results of promises in parallel, serially, or via some combination of both. That's part of their power versus straight callbacks which enforce a serial approach.
I like your approach with your await library. You're probably aware of this, but the jQuery "Deferred" implementation of promises has a similar mechanism that I'm not sure is common in other JavaScript promise implementations:
The great thing about Promises/A+ is that it's so small. I have implemented it in 375 bytes, and was even able to add two convenience functions: https://github.com/timjansen/PinkySwear.js
I gave a talk at JSConf US 2013 about the genesis of this spec, and how I believe it plays into the future of open, developer-driven APIs for the web platform. I hope the video is up soon, but until then, the slides are at http://www.slideshare.net/domenicdenicola/boom-promisesa-was...
Maybe I'm missing something, but I find C#'s async/await much more intuitive (not having written any C# and currently working on a pet project using promises with Node and Q).
My issue with promises is that I find myself working around the API/language when I actually want synchronous code. My app calls a JSON API and then writes the results to three tables (in sequence). In "normal", blocking code:
In which setupDB() returns a chain of three promises and collectData, which loops through the results and attach a new promise to the chain in order to return a chain of `n` promises.
Are these just growing pains of learning a new paradigm or am I using the wrong tool for the job?
Can someone point me to any projects that actually use promises?
If you make your `db.load` method resolve the promise with `this` (where `this` is `db`), and do the same for `setupDB` and `collectData` you can easily chain them without having to have a reference to `db`.
db.load()
.then(setupDB)
.then(collectData);
That way it looks much more like your blocking code.
You are currently basically throwing away the value you `resolve` with, where you should instead resolve with what would be the return value if it was a sync function so you can `.then` the function that takes the return value and returns a promise to be resolved with its return value.
// Sync
var foo = function () { return 'foo' };
var addBar = function (foo) { return foo + 'bar'; }
addBar(foo()) == 'foobar'
// Promise using Q
var foo = function () { return Q.resolve('foo') };
var addBar = function (foo) { return Q.resolve(foo + 'bar'); }
foo.then(addBar).done(function (result) {
result == 'foobar'
});
It's worth noting that C#'s async/await is based directly on promises; they are called `Task<T>` in .NET. Indeed, they share a common ancestor I believe; .NET 4.5's `Task<T>` is derived from F#'s `Async<T>`, and both `Async<T>` and JavaScript promises are based on E's promises.
I wrote a library a while ago that nearly fulfills this entire spec. I've added/changed things that I thought were more intuitive.
https://github.com/kolodny/wttt
The point of having the spec is that libraries can freely exchange data and promises, even if they depend on totally different flow control libraries, while still being certain that error handling and chaining works as expected. It looks like if I build on top of your library, I'm locked in.
This is not to say that it invalidates your library or that every promise library has to comply to A+ or that A+ is the only good way to design promises in JS.
> 3.2.1.1 If onFulfilled is not a function, it must be ignored.
This is idiomatic JS I guess, but it bugs me to bits. IMO the parameter should be a function or it should be null; anything else should throw an error.
`then` is meant to return a promise, i.e. return an asynchronous value; it should never synchronously throw an error.
That said, I somewhat agree (although in JavaScript it should be `undefined`, not `null`). If we were starting clean, instead of with tons of code in the wild that did `.then(null, onRejected)` or `.then(false, onRejected)`, we would have the resulting promise be rejected with a `TypeError` if `onFulfilled` was neither `undefined` nor a function.
Thanks for this discussion... after reading Domenic's slides, watching his talk, and going through the questions here and on the gist, I've filed a bug to try to move Enyo's async implementation to promises after our next release. (https://enyojs.atlassian.net/browse/ENYO-2700) Currently, our code is more like the jQuery 1.5 implementation, but it really lacks the nice error semantics that Promises/A+ has.
While the Promises/A+ specification is primarily focussed on JavaScript, the concept of promises certainly did not originate in JavaScript. For that matter, there are actually a number of implementations of Promises/A+ in other languages and platforms: https://github.com/promises-aplus/promises-spec/blob/master/...
It's still better to use promises as an underlying mechanism, so that you can "yield* promise" or "yield* generator". This approach is now implemented in python tulip framework, and it solves the problem of combining the existing callback-based code with coroutines.
Because promises resolve to one value which can be retrieved long after the promise was resolved. This is a fundamentally different approach than EventEmitters. node's streams are the closest thing to "promise meets event emitter" I'm aware of. But maybe I'm missing the point of your question.
[+] [-] domenicd|12 years ago|reply
https://github.com/promises-aplus/promises-spec
Including a changelog:
https://github.com/promises-aplus/promises-spec/blob/master/...
And the issues still open versus closed in the 1.1 timeframe are at
https://github.com/promises-aplus/promises-spec/issues?miles...
We were hoping to do a revision of the website's look at the time of the 1.1 release as well, mainly adding links to additional resources in the repository (like the implementations list, credits, etc.). A bit sad that we haven't moved fast enough to finish that before making the front page of Hacker News!
[+] [-] SeanDav|12 years ago|reply
I am kind of figuring things out as I go along but if anyone here can point me to such guides, I would be most grateful.
[+] [-] domenicd|12 years ago|reply
http://www.slideshare.net/domenicdenicola/callbacks-promises...
http://www.slideshare.net/domenicdenicola/promises-promises with video at http://www.youtube.com/watch?v=MNxnHbyzhuo
http://www.slideshare.net/domenicdenicola/boom-promisesa-was... which is more inspirational and motivational than practical
Otherwise, in the Q readme we try for a "graduated tutorial" approach; would welcome any feedback you have to make it more friendly. We try to relegate the "list of functions" to the API reference at https://github.com/kriskowal/q/wiki/API-Reference
[+] [-] DanielRibeiro|12 years ago|reply
The author of Promises/A+ also wrote a nice blost post on his You're Missing the Point of Promises [3]
Promises are actually a part of a of a very well understood programming mechanism that involves Futures and Deferred as well[4]
[1] http://blog.jcoglan.com/2013/03/30/callbacks-are-imperative-...
[2] https://news.ycombinator.com/item?id=5466872
[3] https://gist.github.com/domenic/3889970
[4] http://en.wikipedia.org/wiki/Future_%28programming%29
[+] [-] tgriesser|12 years ago|reply
The source should be fairly annotated and is structured similar to Backbone.js, so it might be useful to take a look through and see where/how those functions are being used.
[+] [-] dclowd9901|12 years ago|reply
[+] [-] _greim_|12 years ago|reply
I wrote an alternate implementation of promises in JS (lowercase "p") that uses the former approach: https://github.com/greim/await.js
[+] [-] tlrobinson|12 years ago|reply
That API isn't written into the Promises/A+ spec because it doesn't need to be. That spec is the minimal things necessary for multiple promise implementations to be interoperable.
[+] [-] ufo|12 years ago|reply
I tend to find that the biggest problem with promise libraries is writing code with lots of jumps and more advanced control flow. If you are using an explicit continuation-based approach then doing a jump (for a loop or for breaking out early) is just a matter of calling the appropriate continuation. On the other hand, promises naturally tend to prefer the sort of code where there is only a single return statement at the end (unless you abuse the error handling system but there are all sort of problems if you do that)
[+] [-] drhayes9|12 years ago|reply
You can retrieve the results of promises in parallel, serially, or via some combination of both. That's part of their power versus straight callbacks which enforce a serial approach.
Check out this link to q's documentation: https://github.com/kriskowal/q#combination
[+] [-] andywhite37|12 years ago|reply
$.when()
http://api.jquery.com/jQuery.when/
[+] [-] tjansen|12 years ago|reply
[+] [-] scotth|12 years ago|reply
[+] [-] domenicd|12 years ago|reply
[+] [-] martingordon|12 years ago|reply
My issue with promises is that I find myself working around the API/language when I actually want synchronous code. My app calls a JSON API and then writes the results to three tables (in sequence). In "normal", blocking code:
Using Node and Q: In which setupDB() returns a chain of three promises and collectData, which loops through the results and attach a new promise to the chain in order to return a chain of `n` promises.Are these just growing pains of learning a new paradigm or am I using the wrong tool for the job?
Can someone point me to any projects that actually use promises?
[+] [-] ShellfishMeme|12 years ago|reply
You are currently basically throwing away the value you `resolve` with, where you should instead resolve with what would be the return value if it was a sync function so you can `.then` the function that takes the return value and returns a promise to be resolved with its return value.
[+] [-] domenicd|12 years ago|reply
[+] [-] kolodny|12 years ago|reply
[+] [-] jkrems|12 years ago|reply
This is not to say that it invalidates your library or that every promise library has to comply to A+ or that A+ is the only good way to design promises in JS.
[+] [-] willvarfar|12 years ago|reply
This is idiomatic JS I guess, but it bugs me to bits. IMO the parameter should be a function or it should be null; anything else should throw an error.
[+] [-] domenicd|12 years ago|reply
That said, I somewhat agree (although in JavaScript it should be `undefined`, not `null`). If we were starting clean, instead of with tons of code in the wild that did `.then(null, onRejected)` or `.then(false, onRejected)`, we would have the resulting promise be rejected with a `TypeError` if `onFulfilled` was neither `undefined` nor a function.
[+] [-] unwiredben|12 years ago|reply
[+] [-] andrewcooke|12 years ago|reply
[+] [-] domenicd|12 years ago|reply
[+] [-] jasondenizac|12 years ago|reply
[+] [-] __david__|12 years ago|reply
[+] [-] ricardobeat|12 years ago|reply
Meanwhile, ES6 generators are coming to node v0.12, already in FF and soon to be in Chrome; that is a whole different game.
[+] [-] 1st1|12 years ago|reply
[+] [-] pspeter3|12 years ago|reply
[+] [-] jkrems|12 years ago|reply