Edit - now that you've disclosed the actual code:
You are not using $.Deferred()
correctly.
A typical usage in your context would look like this:
var d;
var tasks = [];
for (var i = 0; i < len; i++) {
// create new deferred object
d = $.Deferred();
// put deferred into tasks object
tasks.push(d);
loadRequireJsModule( "./impl/" + layerJSON.views[i].renderer, function( index, deferred ){
return function( module ) {
layer.views[index].renderer = new module();
// now that this operation is done, resolve our deferred
deferred.resolve();
}
}(i, d));
}
$.when.apply($, tasks).done(function() {
// code executes here when all the deferreds
// have had `.resolve()` called on them
});
Then, when all deferred objects that were put into the tasks array get resolved (by you calling .resolve()
), then $.when()
will fire.
You do not generally pass a callback to $.Deferred()
like you were doing (that's used for something else and only used in special circumstances where you want to modify the deferred object in certain ways).
You MUST resolve or reject each deferred yourself by calling one of the methods on the deferred object that resolves or rejects it (there are four different methods that can be used).
Also, note that this structure runs ALL the async tasks in parallel (e.g. it fires them all at the beginning and then notifies you at the end when all of them have finished). You would need a different structure if you want them to run sequentially where you don't start the second one until the first has finished and so on.
If you want async behavior, then $.when()
expects its arguments to be jQuery deferred
or promise
objects. So, for the structure of your code to work, the return from myAsyncWrapper()
must be a jQuery deferred
or promise
object. That way, $.when()
can monitor the promise objects for completion and when they are all complete, call your .then()
handler.
Then, your async operations must either resolve or reject every one of the deferred objects that you passed to $.when()
because it will only call its own .done()
when ALL the deferred objects you passed to it have been resolved. Or, it will call its own .fail()
if any of the deferred objects you passed to it is rejected.
If you are sure all the arguments you are passing to $.when()
are deferreds or promises and your .then()
handler is still getting called immediately, then your deferreds must already be resolved somehow because that's the likely explanation for why your .then()
handler is called immediately.
If none of the arguments passed to $.when()
are deferred
or promise
objects, then it will resolve itself immediately and thus call your .then()
handler immediately which sounds like the behavior you are experiencing.
If your async operations are ajax calls, then jQuery.ajax()
already returns a promise object that will be resolved when the ajax call completes. You can directly add the return result from jQuery.ajax()
to your tasks array and pass that to $.when()
and it will support your asynchronous behavior.
Using jQuery.ajax()
, here's the concept for using $.when()
with multiple concurrent ajax calls:
var promises = [];
for (var i = 0; i < myNum; i++) {
promises.push($.ajax(...));
}
$.when.apply($, promises).done(function() {
// put code here that runs when all the ajax calls have completed
// the results of all the ajax calls are in
// arguments[0], arguments[1], etc...
}).notify(function() {
// .notify is purely optional and only necessary if you want to be notified as
// each async operation completes
// This will get called as each async operation completes with whatever arguments
// were passed to the success handler
}).fail(function() {
// this will get called immediately if any of the async operations failed
// the arguments are the same as the .done() function except that some may be empty
// if they didn't complete before one of them failed
});
Obviously, you don't have to use all three operations .done()
, .notify()
and .fail()
or you can specify all of them in .then()
- I just included all three with comments for educational purposes.
If you want help with some other type of async operation that doesn't already create its own promise object, then I'd be happy to help if you show and describe the actual operation. Deferreds are confusing to get a handle on initially, but like many things are actually quite simple and extremely useful once it finally sinks in.