3

I have a problem at work: I have a section of installations which are dependent on servers. I want to do this: When a user deletes a server, it loops through installations collection and deletes all dependent installations. For that I use jQuery 'when' function, which is said to wait for a response from the server and then move on to 'then' function. It works flawlessly when there is only one dependent installation. A problem occurs when there are more installations, however, because it moves to the 'then' function immediately after receiving a JSON response.

The question is: How do I make 'when' function wait for all server responses? Eg. I send out three delete requests through $.postJSON and want to move on after I get all three responses. If it's not possible with 'when', what should I use to make it happen? If it helps, I maintain all my entities collections with KnockoutJS. Thanks!

EDIT: I have it like this:

$.when(DeleteDependentInstallations())
.then (function() {
   ...
});

DeleteDependentInstallations looks like (pseudocode):

Search the installations collection;
If installation.ID equals server.InstallationID
{
  Add to dependent installations collection;
}
Repeat until the whole collection is searched;

for (i = 0; i < dependentInstallations.length; i++)
{
  DeleteInstallation(dependentInstallations[i]);
}

DeleteInstallations is a simple function using $.postJSON function.

The problem is the .then function executes immediately after the first JSON response.

Filip Vondrášek
  • 1,208
  • 1
  • 13
  • 26
  • Code. Example. Whathaveyoutried. – PitaJ Aug 27 '12 at 18:14
  • `$.when()` waits for either *all resolves* **or** *the first reject*. This questions seems to be a duplicate. I've made a modified version of `$.when()` and there's a couple of other answers over at **[jQuery.when - Callback for when ALL Deferreds are no long 'unresolved' (either resolved or rejected)?](http://stackoverflow.com/questions/5824615/jquery-when-callback-for-when-all-deferreds-are-no-long-unresolved-either-r)** – hippietrail Aug 27 '12 at 18:43
  • I added a pseudocode of how I do it. I think this case is a bit different that the one at the link you posted, hippietrail. – Filip Vondrášek Aug 27 '12 at 19:18
  • why did you include knockoutjs on this? Is Knockout something your'e using elsewhere? Or is Knockout something you thought would be a good fix? – deltree Aug 27 '12 at 19:19
  • A similar question http://stackoverflow.com/questions/11432358/chaining-multiple-asynchronous-methods-in-javascript/11432543#11432543 – Dmitry Osinovskiy Aug 27 '12 at 19:22
  • This is only a small part of the whole website, which uses Knockout as the presentation layer. – Filip Vondrášek Aug 27 '12 at 19:23
  • Does `DeleteDependantInstallations()` return an array of jquery Promises? If you made that return an array of the return values of your ajax calls, when() *should* wait for each of them to complete. – Ben Lesh Aug 27 '12 at 19:28
  • @blesh: This is the first time I hear of jQuery promises, how would I do that? – Filip Vondrášek Aug 27 '12 at 19:35
  • I added an answer that explains what I mean (I hope). Good luck. – Ben Lesh Aug 27 '12 at 19:44

1 Answers1

1

I think you need to have DeleteDependentInstallations return an array of JQuery deferreds. $.when allows you to pass multiple arguments to it in order to let it know it has to wait for each one.

I don't know the whole context of what you're doing, but I think something like this might work:

function DeleteDependentInstallations() {
     var installations = getDependantInstallations();
     var promises = [];
     for (var i = 0; i < installations.length; i++) {
         var installation = installations[i];
         promises.push(DeleteInstallation(installation));
     }
     return promises;
}

function DeleteInstallation(installation) {
      //do whatever here, but return the result of $.ajaxPost
      return $.post('/foo', installation);
}

Now when you use that method, it should wait for all returned promises to complete.

$.when.apply(null, DeleteDependentInstallations()).then(function() { alert('wee!'); });

The .apply() is so we can pass an array as an arguments collection.

EDIT: I was confusing "deferreds" and promises in my head. Deferreds are what the $.ajax calls return, and a promise is what the $.when() function returns.

EDIT2: You might also want to look at the .done() method, if the behavior of .then() doesn't suit your needs.

pimvdb
  • 151,816
  • 78
  • 307
  • 352
Ben Lesh
  • 107,825
  • 47
  • 247
  • 232