DeividKamui
DeividKamui

Reputation: 392

How to execute multiple ajax calls and get the result?

Hi I want to execute a batch of ajax calls and get the response and then render the results for the user.

I'm using this code but it is not working because the render function executes before all the ajax responses have been collected.

serviceQuery: function (id) {    

   return $.getJSON(SERVICEURL + "/", id);

},

queryService: function(data){

   var self = this;
   var queries = [];
   var results = [];

   $.each(data, function (index, value) {
        queries.push(self.serviceQuery(value.id)); 
   });

   $.when(queries).done(function (response) {

         $.each(response, function (index,val) {

             val.then(function (result){

                 results.push(result[0]);                      

             });

         });

         self.renderResult(results);

   });

},

renderResult: function(results){

     $.each(results, function (index, value) {
     ///Error here cause the value.Name is undefined
          console.info(value.name);
     });

}

Any Idea on how to wait for all the ajax calls to finish before execute the render function?

Upvotes: 0

Views: 953

Answers (3)

guest271314
guest271314

Reputation: 1

Use .apply() at $.when() call to handle an array of Promises. Note also that .then() returns results asynchronously

let queries = [
  // `$.ajax()` call and response
  new $.Deferred(function(dfd) {
                                    
    setTimeout(dfd.resolve, Math.floor(Math.random() * 1000)
      // response, textStatus, jqxhr
    , [{name:"a"}, "success", {}])
    })
    // `$.ajax()` call and response
  , new $.Deferred(function(dfd) {
    setTimeout(dfd.resolve, Math.floor(Math.random() * 1000)
      // response, textStatus, jqxhr
    , [{name:"b"}, "success", {}])
    })
];

$.when.apply(null, queries)
.then(function() {
  renderResult($.map(arguments, function(res) {return res[0]}));   
});

function renderResult(results) {
  $.each(results, function (index, value) {
    console.info(value.name);
  });
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>

Upvotes: 2

intentionally-left-nil
intentionally-left-nil

Reputation: 8274

I see one potential issue here:

$.when(queries).done(function (response) {

     $.each(response, function (index,val) {

         val.then(function (result){

             results.push(result[0]);                      

         });

     });

     self.renderResult(results);

});

Basically, your pseudocode says this: For each return value from your $.when() command, take the value of that and return a new promise (via val.then). However, because you never wait for the val deferred to run, results.push is not guaranteed to be called before your self.renderResult(results) call.

The code looks weird to me in that you would need two nested deferreds for an ajax call. So I think a larger meta issue is why do you need to do val.then in the first place. However, given the current code, you would need to do something like this:

var innerDeferreds = [];
$.each(response, function (index,val) {

     innerDeferreds.push(val.then(function (result){

         results.push(result[0]);                      

     }));;

 });
 $.when(innerDeferreds).then(function() { self.renderResult(results); });

Again, my guess is that you don't need the val.then in the first place, but I would need to look in a debugger to see what the values of response, index and val are. (If you set up a jsfiddle that would be super helpful!)

Upvotes: 0

Jerhemy
Jerhemy

Reputation: 590

Change the $.each to a for loop. It is possible that the .then on the value isn't finished processing before the loop completes. $.each is synchronous but the .then generally, means it's a promise and isn't synchronous.

$.each(response, function (index,val) {
    val.then(function (result){
        results.push(result[0]);                      
    });
});

Change too

for(var idx = 0; idx < response.length; idx++) {
    results.push(response[idx]);
}

or keeping with the each you may just need to remove the .then call.

$.each(response, function (index,val) {
    results.push(val[0]);                      
});

Upvotes: 0

Related Questions