5 ms·
Promises/A+
- andrewcooke 13y agowouldn't it be good to explain somewhere, early on, that this is for javascript?
- __david__ 13y agoWell, the link in the first sentence does point to http://commonjs.org/.. http://commonjs.org/...
- domenicd 13y agoThis is actually a really good point, haha! Filed, and will fix in the upcoming so-close-to-done 1.1 revision: https://github.com/promises-aplus/promises-spec/issues/135 https://github.com/promises-aplus/promises-spec/issues/135
- jasondenizac 13y agoWhile 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/implementations.md#in-other-languages https://github.com/promises-aplus/promises-spec/blob/master/...
- kolodny 13y agoI 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 https://github.com/kolodny/wttt
- jkrems 13y agoThe 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.
- _greim_ 13y agoMy 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 https://github.com/greim/await.js
- drhayes9 13y agoI 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. Check out this link to q's documentation: https://github.com/kriskowal/q#combination https://github.com/kriskowal/q#combination
- ufo 13y agoTBH, both callbacks and promises are kind of similar when it comes to running things in parallel. In both cases you use the same sort of semaphore pattern and its something thats easy to hide behind a library function. function parallelCallbacks(cbs, onAllDone){ var nLeft = cbs.length; var results = [] var onOneDone = function(res){ results.push(res); nLeft -= 1; if(nLeft <= 0){ onAllDone(results) } } for(var i=0; i<cbs.length; i++){ cbs[i](onOneDone); } } parallelPromises([ function(){ return promise(10) }, function(){ return promise(20) } ).then(function(results){ ... }); parallelCallbacks([ function(onDone){ onDone(10) }, function(onDone){ onDone(20) } ], function(results){ ... });
- tlrobinson 13y agoOne of the main differences is in error handling. Much like exceptions, errors are automatically propagated to the first error handler in the promise chain. With Node-style callbacks you need to explicitly check for errors and re-emit them at every stage. I also think promises' use of return values vs passing a callback as an argument is conceptually cleaner and easier to compose.
- SeanDav 13y agoI have just started doing development in Node.js. Originally using the excellent caolan/async library (https://github.com/caolan/async 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 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.
- domenicd 13y agoI have given several talks, for which slide decks and one video are available: http://www.slideshare.net/domenicdenicola/callbacks-promises-and-coroutines-oh-my-the-evolution-of-asynchronicity-in-javascript http://www.slideshare.net/domenicdenicola/callbacks-promises... http://www.slideshare.net/domenicdenicola/promises-promises http://www.slideshare.net/domenicdenicola/promises-promises with video at http://www.youtube.com/watch?v=MNxnHbyzhuo http://www.youtube.com/watch?v=MNxnHbyzhuo http://www.slideshare.net/domenicdenicola/boom-promisesa-was-born 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 https://github.com/kriskowal/q/wiki/API-Reference
- SeanDav 13y agoHi Domenic, Thanks for those links - I will check them all. There is another one of yours (co-speaker) that I thought was excellent: Redemption from Callback Hell (http://www.youtube.com/watch?v=hf1T_AONQJU http://www.youtube.com/watch?v=hf1T_AONQJU)
- domenicd 13y agoOh yes, I always forget about this one because it's not on my SlideShare, but you're right, it's really excellent! Michael did a great job putting that together and I was honored he invited me to share the stage.
- pspeter3 13y agoJust out of curiosity, why don't we use node's event emitters to wrap callbacks as promises?
- jkrems 13y agoBecause 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 13y agoIt'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): https://github.com/promises-aplus/promises-spec https://github.com/promises-aplus/promises-spec Including a changelog: https://github.com/promises-aplus/promises-spec/blob/master/changelog.md 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?milestone=2&page=1&state=open 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!
- domenicd 13y agoI 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-born http://www.slideshare.net/domenicdenicola/boom-promisesa-was...
- tjansen 13y agoThe 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 https://github.com/timjansen/PinkySwear.js
- scotth 13y agoGreat project name.
- willvarfar 13y ago> 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.
- domenicd 13y ago`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.
- willvarfar 13y agoHmm null is easier to pass on purpose and undefined is easier to pass by accident. Sending in undefined for a non-trailing argument takes effort. I think the literal null is far more communicative of the developers intent. But the general point is, JS APIs tend to fail silently on error by design and that's something that bugs me, literally. Bugs. Lots of them. I agree regards returning a failure rather than throwing an exception, though.
- ricardobeat 13y agoPromises are coming of age too late, and still have unsolved fundamental issues. 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 13y agoIt'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.
- martingordon 13y agoMaybe 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: results = getResults(); writeTable1(results.foo); writeTable2(results.bar); writeTable3(results.baz); Using Node and Q: db.load().then(()-> setupDB(db)).then(()-> collectData(db)).done() 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 13y agoIf 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' });
- domenicd 13y agoIt'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.
- unwiredben 13y agoThanks 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 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.