3

I have a for loop statement, each loop will execute an ajax call.

$.each(arr, function(i, v) {
    var url = '/xml.php?id=' + v;
    $.ajax({
        url: url,
        type: 'GET',
        dataType: 'xml',
        success: function(xml) {
            if ($(xml).find('Lists').attr('total') == 1) {
                // some code here
            }
        },
        complete: function() {
            // some code here
        }
    })
})

I want to run code after all ajax call completed under the loop, I have tried to place the code below to last line, it is not executed when the ajax call completed

    if (i == arr.length - 1) {
        // some code here
    }

Therefore, if I have 10 times of loop, there are 10 times of ajax call. I want to run a code after there 10 times of ajax call completed, any ideas?

Is it better to use .ajaxComplete() or .done() to achieve it?

Thanks

Charles Yeung
  • 38,347
  • 30
  • 90
  • 130
  • I think that you need to use ajaxQueue, try this link https://gist.github.com/gnarf37/1039247 – Red Jun 06 '13 at 07:30

2 Answers2

13

Try using $.when()

var arr = [];
$.each(arr, function(i, v) {
    var url = '/xml.php?id=' + v;
    var xhr = $.ajax({
        url: url,
        type: 'GET',
        dataType: 'xml',
        success: function(xml) {
            if ($(xml).find('Lists').attr('total') == 1) {
                // some code here
            }
        },
        complete: function() {
            // some code here
        }
    });
    arr.push(xhr);
})

$.when.apply($, arr).then(function(){
    console.log('do')
})
Arun P Johny
  • 384,651
  • 66
  • 527
  • 531
  • Thanks for the suggestion, but what is the meaning of `arr.push(xhr);` and `.apply($, arr)`? Thanks. – Charles Yeung Jun 06 '13 at 08:28
  • If you go through the doc for `when` you will find that the callbacks registered for when will get completed once all the differed objects passed to `when` is resolved. Now here we have to collect all the xhr objects created by the ajax call, so I'm using an array to store those xhr objects using `arr.push(xhr);` – Arun P Johny Jun 06 '13 at 08:31
  • I got it, thanks. But how about `.apply($, arr)`, what is the meaning of this code? – Charles Yeung Jun 06 '13 at 08:37
  • The `when` function wants the list of differred objects to be passed as different params like `$.when(diff1, diff2, ..., diffn)`, in our case we have a list of `xhr` objects, the [.apply()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply) is used to convert the array into parameter list – Arun P Johny Jun 06 '13 at 08:44
  • Thanks again. If you don't mind I have one more question...I added `console.log(i)` below `ajax success property` and I found that the execution is not in ordering(e.g. 0, 1, 3, 2, 4). How can I change the code to make the ajax function executed in order? – Charles Yeung Jun 06 '13 at 09:01
  • @CharlesYeung easy answer you can't because of the asynchronous nature of ajax – Arun P Johny Jun 06 '13 at 09:08
  • Oh sorry, for your reference, just found http://stackoverflow.com/questions/133310/how-can-i-get-jquery-to-perform-a-synchronous-rather-than-asynchronous-ajax-re – Charles Yeung Jun 06 '13 at 09:16
  • @CharlesYeung even if it is possible, it is something you should never to if possible because it iwll block your browser tab from doing anything till all the ajax requests are completed – Arun P Johny Jun 06 '13 at 09:17
0

I came across a similar scenario but inside the loop, the AJAX call was done in another function call (called fetchData).

so I made the fetchData function return a Promise coming from the AJAX call and I chained it using the then clause in order to process the response.

Here's the Plunker link

$(document).ready(function() {
  var message = '';

  process();

  function process() {
    var promises = [];
    for (var i = 0; i < 3; i++) {
      var promise;
      (function (index) {
        promise = fetchData(index).then(function (response) {
          // do something with the response.
          message += 'Iteration ' + index + '\n';
        });
      })(i);

      promises.push(promise);
    }

    $.when.apply($, promises).then(function () {
      // do something after all the AJAX calls are completed.
      alert(message);
    });
  }

  function fetchData(param) {
    return $.ajax('data.json')
      .success(fetchDataSuccess)
      .error(fetchDataFailed);

    function fetchDataSuccess(response) {
      return response;
    }

    function fetchDataFailed(error) {
      console.error(error);
    }
  }
});
Abdul Mateen Mohammed
  • 1,864
  • 1
  • 12
  • 21