The problem you are having is that you are ultimately defining, resolving and returning a single deferred, even though your loop indicates that you are intending to track multiple deferreds. $.when
expects multiple deferreds to be passed as individual arguments. In order for the example to work, I included a mock asyncEvent
function pulled from the jQuery documentation. See the below snippet to see everything working as expected:
function asyncEvent() {
var dfd = jQuery.Deferred();
// Resolve after a random interval
setTimeout(function() {
dfd.resolve( "hurray" );
}, Math.floor( 400 + Math.random() * 2000 ) );
// Return the Promise so caller can't change the Deferred
return dfd.promise();
}
function makeAjac(i) {
var dfd = $.Deferred()
asyncEvent().then(function(res) {
asyncEvent().then(function(res) {
console.log(`request pair ${i} complete.`);
dfd.resolve();
});
});
return dfd.promise();
}
function ajac() {
var promisesArray = [];
for(var i=0;i<2;i++){
promisesArray.push(makeAjac(i));
}
return promisesArray;
}
$.when.apply($, ajac()).then(function(){
console.log("reached");
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
What we've done here is pull the code that was executing inside your for
loop into its own function makeAjac
which returns the promise for its particular iteration through the loop. In the original ajac
then we push those returned promises into our promisesArray
, which we in turn return from ajac
. Finally, we leverage .apply
in order to pass the promises in the array as separate arguments to $.when
. As you can see from running the snippet, this functions as expected.