23

I have used promises in jQuery slightly before - but I am having trouble applying it to this scenario. I prefer to use the $.when() and $.done() methods to achieve this.

From what I understand I need to build a $.Deferred object which logs the requests and when those requests are finished - fire the callback. In my code below the callback is firing before the ajax requests and not after - maybe I just need some sleep

I know my code is incomplete I have been struggling to apply it with the addition of the for loop.

http://jsfiddle.net/whiteb0x/MBZEu/

var list = ['obj1', 'obj2', 'obj3', 'obj4', 'obj5'];
var callback = function() {
  alert("done");
};
var requests = [];

var ajaxFunction = function(obj, successCallback, errorCallback) {
  for(i = 0; i < list.length; i++) {
    $.ajax({
      url: 'url',
      success: function() {
            requests.push(this);
      }
    });
  }
};
$.when($.ajax(), ajaxFunction).then(function(results){callback()});
user1982408
  • 337
  • 1
  • 3
  • 8

2 Answers2

58

The arguments to $.when should be the return value of $.ajax, which also doesn't need to be called separately -- that makes no sense. You want something like this:

for (i = 0; i < list.length; i++) {
   requests.push($.ajax(...));
}
$.when.apply(undefined, requests).then(...)

The reason that .apply is needed is because $.when can take multiple arguments, but not an array of arguments. .apply expands essentially to:

$.when(requests[0], requests[1], ...)

This also assumes that the requests can be completed in any order.

http://jsfiddle.net/MBZEu/4/ -- notice that 'done' is logged to the console after all of the success messages.

Explosion Pills
  • 188,624
  • 52
  • 326
  • 405
  • 3
    how to handle all the results at once? – MK Yung Oct 21 '13 at 10:46
  • $.when.apply(undefined, requests).done(function(response1, response2, ...){ if(response1[1]=="success") {// DoSomething with response1[0]} }); – Anthony Graglia Nov 07 '13 at 13:43
  • Still, how to get all the responses in an array? You cannot expect one to know how many responses are going to be there before hand. – Prakhar Mishra Sep 25 '14 at 05:04
  • 2
    As @MKYung asked, it could be a problem to handle the results... because, if you have just one element in the list of requests you'll got one retuning result in the method `done` but divided into three parameter `jqXHR.done(function( data, textStatus, jqXHR ) { ... });`. But with multiple requests you got all the three parameters wrapped in arrays e.g. `jqXHR.done(function( [data, textStatus, jqXHR], [data, textStatus, jqXHR], ... ) { ... });`. To handle it inside the `done` method you have to know the count of requests, in this case `list.length` to decide how to parse the results... – algorhythm Nov 21 '14 at 12:06
9

I share an easy example that could help you to handle multiple requests and their responses:

var arr = [
    $.ajax({url:"test1.php"}),
    $.ajax({url:"test2.php"}),
    $.ajax({url:"test3.php"})
];
$.when.apply( undefined, arr ).then(function() {
    var objects=arguments;
    console.dir(objects);
});
Kanabos
  • 420
  • 4
  • 11