1

I am writing a google content script and my program needs to make roughly 30 AJAX calls to the server. I am using JQuery's .when function in conjunction with .apply to pass in an array to the .when function. I am also using .done and I want to be able to pass in an array of arguments that will take on the deferred objects from the .when function. Is there any way to do this? This is what I am trying to do.

    var callback = function(a) {
  console.log("done", a);
};
var requests = [];
var requestArray = [];
  for(i = 0; i < liclass.length; i++) {
  requests.push($.ajax({
      url: liclass[i],
     success: function() {;
      }
    }));
            var str = "messageArg" + i
        requestArray.push(str)
  }

$.when.apply($, requests).done(function(requestArray){
callback(requestArray)});
  • 1
    You're trying to do what? Why are you using the same name for the argument in the done() callback that should be the data, as for some array filled with strings, and what is not working now, are there any errors etc ? – adeneo Mar 14 '14 at 21:32
  • It looks like you just have to change `function(requestArray)` to `function()` so that you don't shadow the variable you create outside the function. – Felix Kling Mar 14 '14 at 21:36
  • How about just passing in the callback `$.when.apply($, requests).done(callback);` – adeneo Mar 14 '14 at 21:36

3 Answers3

3

Are you looking to put the ajax responses in an array and have a callback execute when all the ajax calls have returned? You can actually get such an array from the arguments passed to .done().

According to the documentation for $.when:

  1. If you call .done() on the Promise returned by $.when when it is passed a single ajax request Deferred, the first argument to the callback function will be the response data.
  2. If you call .done() on the Promise returned by $.when when it is passed multiple ajax request Deferreds, "the arguments will be the jqXHR objects for the requests, in the order they were given in the argument list." That statement appears to be a bit inaccurate, however, because a comment in the example states: "Each argument is an array with the following structure: [ data, statusText, jqXHR ]."

Therefore you could try:

var requests = $.map(liclass, function(url) {
    return $.ajax(url);
});

$.when.apply($, requests).done(function() {
    var results = (requests.length > 1)
        ? $.map(arguments, function(a) { return a[0]; })
        : [arguments[0]];
    console.log(results);
});

Demo on JSFiddle

John S
  • 21,212
  • 8
  • 46
  • 56
0

If you look at the examples for $.when, you see that the call back gets passed an argument for each promise. If that promise came from an Ajax call, then each argument is an array of the form [ data, statusText, jqXHR ].

So you you just have iterate over the arguments and extract the first element. $.map makes that very easy:

$.when.apply($, requests)
  .then(function() {
    return $.map(arguments, function(v) {
      return v[0];
    });
  })
  .done(callback);
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
0

I'm fairly new to the deferred stuff (and jQuery in general), but my helper function below seems to work. None of the requests depend on each other for data. I'll probably write a similar helper function to handle chained requests, which will have to use .then().

function sendRequests(requests, callbacks) {
    $.when(...requests).done(function(...results) {
            results.forEach(function(result, index) {
                    callbacks[index](JSON.parse(result[0]));
        });
    });
}

function req1Callback(data) {
    // do something with data object
}

var req1 = $.get(), // arguments omitted
    req2 = $.get(),
    req3 = $.get();

sendRequests([ req1, req2, req3 ], [ req1Callback, req2Callback, req3Callback ]);
Conrad Damon
  • 711
  • 6
  • 3