I run into the situation where I have multiple JQuery Promises in an Array
var arrayOfPromises = [ $.Deferred(), $.Deferred(), $.Deferred(), $.Deferred() ]
and need to turn it into a JQuery Promise of an Array
var promiseOfArray = someTransform(arrayOfPromises)
where
promiseOfArray.done(function(anArray){
alert(anArray.join(","));
});
creates an alert with text
result1,result2,result3,result4
I currently define someTransform
in coffeescript as
someTransform = (arrayOfPromises) ->
$.when(arrayOfPromises...).pipe (promises...) ->
promises
which transforms to the following javascript
var someTransform,
__slice = [].slice;
someTransform = function(arrayOfPromises) {
return $.when.apply($, arrayOfPromises).pipe(function() {
var promises;
promises = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
return promises;
});
};
Here is a jsFiddle of the result I'm looking for.
I was wondering if there is a better(shorter,cleaner) way to define someTransform
to achieve the same result?
You can just apply the array as the arguments to
$.when
.To make the usage of this clearer, I like adding a method to
$
:Now you can do:
Update: By default, the
done
handler gets each result passed as a separate argument; you don't get an array of results.Since you need to handle an arbitrary number of Deferreds, you can use the special implicit
arguments
object to loop over the results.If you really just want to join the string result of all your Deferreds, we can employ a little array hackery.
arguments
is array-like, but is not anArray
:If you want to return an array of results to your
done
callback, we can tweakwhenall
to do it:It also bothered me alot to always type the "ugly" line
$.when.apply
when we need to invoke it on multiple promises. ButFunction.prototype.bind
for the rescue!Now, we can just call
Function.prototype.bind
is part of ES5 and is very widely available across browsers. There are a ton of easy shims available if you need to support very old'ish browsers aswell