-
Notifications
You must be signed in to change notification settings - Fork 395
Using with jQuery
when.js works with jQuery Deferred. Even though jQuery Deferred passes the Promises/A duck-type test, it is not Promises/A compliant. However, when you pass any jQuery thenable (jQuery Deferred or the result of calling .promise()
) to when.js's when()
, it will be assimilated, and when()
will return a Promises/A compliant promise. Thus, any downstream .then()
calls will be Promises/A compliant.
when.js's when()
and Promise implementation will also assimilate any jQuery Deferred (in fact, any non-compliant promise) that is returned by a callback or errorback in a chain of promises, thus preserving Promises/A forwarding even when non-compliant promises get into the mix.
Here is an example of how when.js assimilates jQuery thenables and guarantees Promises/A behavior.
All of when.js's promise array handling methods, like when.all()
, when.reduce()
, etc. will work with a mixed array of jQuery thenables, when.js Promises or Deferreds, any other Promises/A promises, and immediate values. This is one of the advantages of when()
(read more here).
Unfortunately, $.when()
does not accept Promises/A promises. It accepts any object that has a .promise()
method. So, there is no way to pass a when.js Promise or Deferred, or any Promises/A compliant promise directly to $.when()
.
To use $.when()
with a Promises/A promise, you have to wrap it in an object that has a .promise()
method:
var promise = methodThatReturnsAPromisesAPromise();
// Can't pass promise directly
// Wrap it in an object with a promise() method, so that $.when() will understand
$.when({
promise: function() {
// return compliant promise
return promise;
}
}).then(...);
Ideally, we'd like to see $.when()
deal directly with Promises/A compliant promises, since it's a proposed CommonJS standard, but the object-with-a-promise-method approach is only jQuery-specific.
If you pass multiple jQuery Deferreds to $.when()
it will join them--that is, it will return a promise that resolves when all the input Deferreds have resolved.
var joined = $.when(deferred1, deferred2)
.then(function(result1, result2) {
// do something with result1 and result2
});
// subsequent callbacks can be registered via joined.then()
when.all()
achieves the same goal. Passing an array of promises to when.all()
will join them, returning a promise that will resolve when all the promises in the array have resolved.
var joined = when.all([promise1, promise2],
function(results) {
// do something with results[0] and results[1]
}
);
// subsequent callbacks can be registered via when(joined, callback)
// or joined.then()
One difference between the two is how the joined callbacks are invoked. when.js always invokes callbacks with a single parameter, which in this case, is an array of the results, and $.when()
invokes its callbacks with an argument list.
There are, of course, valid use cases for both styles, so when.js provides a helper module when/apply that allows you to spread the callback parameters. Here is the example above, modified to use when/apply
:
var apply = require('when/apply');
var joined = when.all([promise1, promise2],
apply(function(result1, result2) {
// do something with result1 and result2
})
);