3

I have been researching jquery deferred objects for a while now and I'm stumped on one thing.

The "done," "always," "then," etc methods take, as their arguments, functions which should be called when the deferred object is resolved.

However I tried chaining requests by passing a deferred object into the "always" method, and that seems to work too:

// A is an array of data
var req = ajax(url + "?d=" + A[0]).done(processResults).fail(reportFailure);
for (var i = 1 ; i < A.length ; i++) {
  var tmp = ajax(url + "?d=" + A[i]).done(processResults).fail(reportFailure);
  req.always(tmp);
  req = tmp;
}

However, it doesn't really work. Because when I follow the above code with this:

req.always(foobar);

foobar seems to get called at some random time, not necessarily after the last element in the array is processed.

Would it be better to use when?

// A is an array of data
var req = $.when(ajax(url + "?d=" + A[0]).done(processResults).fail(reportFailure));
for (var i = 1 ; i < A.length ; i++) {
  req = $.when(req, ajax(url + "?d=" + A[i]).done(processResults).fail(reportFailure));
}
req.always(foobar);

Would the above code (using "when") result in the ajax requests happening one after the other, or would they occur simultaneously?

I looked into chaining with "pipe" by the way, but because of scoping issues I think it would be harder to use "pipe" with a for loop as above.

Also, why does the original code "almost work"? What is happening there? Is it executing the deferred object as if it were a function, and what happens when it does that?

eeeeaaii
  • 3,372
  • 5
  • 30
  • 36
  • p.s.: I tried using $.when and it does appear to work. However I still don't get why doing it the other way "sort of" worked. This seems like a better way to create chains of requests than by using pipe -- but I'm not sure if that is how "when" was intended to be used. – eeeeaaii Sep 29 '11 at 21:49
  • .pipe() is useful when the result of an ajax call are used to build the input of another ajax call. In your case it looks like parallel ajax calls, merged using $.when(), are more appropriated. In my answer I show you how to register a single successcallback using .done() on the merged Deferred – olivieradam666 Sep 29 '11 at 22:30
  • p.p.s. using $.wait doesn't really work. But the solution with "pipe", below, does appear to work, though I do have to resolve the scoping issue with "i" – eeeeaaii Sep 30 '11 at 15:47

1 Answers1

2

You should build an array and use javascript apply :

//create an array of one deferred per element
var requests =  $.map(A, function(index, a){return= $.ajax(url + "?d=" + a);});
//merge all deferreds into a single one
var mergedRequest = $.when.apply(null, requests);

mergedRequest.done(function(res0, res1, ...){
   //your code goes here
   //if you want results as an array just use arguments
   arguments.length == A.length;
});

EDIT: If you want your calls to be made serially do :

var result = $.ajax(url + "?d=" + A[0]);
for (var i = 1 ; i < A.length ; i++) {
  result = result.pipe(function() {
    return $.ajax(url + "?d=" + a[i]);
  }
}
result.done(processResults).fail(reportFailure);
olivieradam666
  • 4,522
  • 2
  • 20
  • 25
  • The thing is, I don't want them parallelized. I want them serialized. – eeeeaaii Sep 29 '11 at 22:42
  • That second thing seems to work -- thanks -- though I think there might be a scoping issue with the variable "i" -- but that's fixable. – eeeeaaii Sep 30 '11 at 15:46