I am trying to use jQuery's $.when.apply to wait for an unknown number of requests to finish before calling the next function (loadTab). I thought I was using it correctly, but it is definitely not waiting for all the requests to finish before loadTab() is called, so I'm not sure what is wrong. Here is my code:
function update(changes) {
var deferreds = [];
// must loop over changes and call individual requests
for(var i = 0; i < changes.length; i++) {
var direction = changes[i]['direction'];
var data = changes[i]['data'];
if(direction == 'add') {
deferreds.push[add(data)];
}
else if(direction == 'edit') {
deferreds.push[edit(data)];
}
else if(direction == 'delete') {
deferreds.push[delete(data)];
}
}
return $.when.apply($, deferreds); // this when is resolving too soon
}
function add(data) {
return $.ajax({
url: 'add',
data: data,
method: 'post',
error: ajaxErrorFcn
})
.then(function(response) {
handleTimeout(response);
});
}
function edit(data) {
return $.ajax({
url: 'edit',
data: data,
method: 'post',
error: ajaxErrorFcn
})
.then(function(response) {
handleTimeout(response);
});
}
function delete(data) {
return $.ajax({
url: 'delete',
data: data,
method: 'post',
error: ajaxErrorFcn
})
.then(function(response) {
handleTimeout(response);
});
}
// this is the sequence of events I'm trying to sort out
showLoad('#container');
var changes = buildChangesArray();
update(changes)
.then(function(response) {
if(handleTimeout(response)) {
// this is executing before the requests triggered by update() are complete
return loadTab()
.then(function(response) {
// do some other stuff
});
}
})
.then(function(response) {
hideLoad('#container');
});
Update:
The original issue was resolved (There was a typo in my calls to .push(), used brackets instead of parentheses), but now I have a new issue with this code. I need to modify the update() function to run the delete actions first, and then run the add and edit actions. This is what I have, but now I am seeing the add and edit actions start to run before the delete actions finish:
function update(changes) {
var deferreds = [];
var deletes = [];
// must loop over changes and call individual requests
for(var i = 0; i < changes.length; i++) {
var direction = changes[i]['direction'];
var data = changes[i]['data'];
if(direction == 'add') {
deferreds.push(add(data));
}
else if(direction == 'edit') {
deferreds.push(edit(data));
}
else if(direction == 'delete') {
deletes.push(delete(data));
}
}
// we need to perform all the delete operations first, then the adds/edits
return $.when.apply($, deletes) // this when is resolving too soon
.then(function(response) {
return $.when.apply($, deferreds);
});
}
Well, looks like I found my own solution :)
I think the problem was that when pushing the asynchronous calls to add(), edit(), and delete() into the arrays, they are also getting called at that point! This wasn't a problem in the first version because then it didn't matter what order the adds, edits, and deletes were performed in as long as they were all done before loadTab() was called. However, it does pose a problem if all the deletes need to be called before calling any adds or edits, because any adds or edits found in the array before the deletes will start running as soon as they are pushed to the array rather than waiting for the deletes.
To fix this, I changed the code to the following:
function update(changes) {
var loop = function(deleteOnly) {
var array = [];
// must loop over changes and call individual requests
for(var i = 0; i < changes.length; i++) {
var direction = changes[i]['direction'];
var data = changes[i]['data'];
if(direction == 'add' && !deleteOnly) {
array.push(add(data));
}
else if(direction == 'edit' && !deleteOnly) {
array.push(edit(data));
}
else if(direction == 'delete' && deleteOnly) {
array.push(delete(data));
}
}
return array;
};
// we need to perform all the delete operations first
return $.when.apply($, loop(true)) // true means only get the deletes
.then(function(response) {
return $.when.apply($, loop(false)); // false means only get the adds/edits
});
}
So the requests are still starting running as soon as they are pushed into the array, but this way we can separate the deletes to makes sure they finish first.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With