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.
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)
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
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){
...
});I also think promises' use of return values vs passing a callback as an argument is conceptually cleaner and easier to compose.
That said, I still feel that both promises and explicit callbacks kind of suck in their own way. Callback code is usually much more verbose and has bad error handling while promises are bad at "jumpy" control flow. When I last worked in a big JS project it got bad enough that I eventually wrote my own control flow library on top of the base Dojo promises we were using so nowadays if I had to work with a big JS project again I would definitely try to use of those tools that add async control flow to the language and compile doen to regular continuations (looks nice like promises, can use loops, break and return like regular JS and raw callbacks don't need extra runtime support)
The hard problem that promises solve are
1. Its more similar to regular code versus explicit CPS (no pyramid of doom, use "return" to return values, can store promises in data structures or pass them around to other functions)
2. Error handling. Regular Javascript has try-catch blocks for exception handling but those don't work with async code. Promises let you use exceptions in async code without having to worry about error callbacks.
$.when()
I wrote an alternate implementation of promises in JS (lowercase "p") that uses the former approach: https://github.com/greim/await.js