2

I have an ajax request that grabs some data and then splits it up into an array. The array length is variable.

  var ajax1 = $.ajax({
    url: 'myurl.php',
    type: "GET",
    dataType: "jsonp",
    success: function (data) {

      //create an array

    }

  });

Once I have the array, I want to loop through it and in each iteration run another AJAX request. I put it inside a $.when to make sure the initial ajax request was complete:

  $.when(ajax1).done(
    function() {

      for (i = 0; i < array.length; ++i) {

        $.ajax({
          url: 'anotherurl?=' + myarray[i],
          type: "GET",
          dataType: "jsonp",
          success: function (data) {

            //do stuff here

          }
        });

      }

    }
  )

My question is, how can I get a message box to pop up when the for loop has completed all the AJAX requests? A simple alert('complete') at the end of the loop won't work as the AJAX is done async.

Lee
  • 1,485
  • 2
  • 24
  • 44
  • Possible duplicate of [How to wait until jQuery ajax request finishes in a loop?](http://stackoverflow.com/questions/20291366/how-to-wait-until-jquery-ajax-request-finishes-in-a-loop) – madalinivascu Aug 03 '16 at 08:45
  • a better solution will be to do a maximum of 2 ajax calls – madalinivascu Aug 03 '16 at 08:46

3 Answers3

9

As of JQuery 1.5, $.ajax() return an object which implement the promise interface, so you can store all of those promises in an array and wait for them to finish using Promise.all().

Something like:

  var root = 'http://jsonplaceholder.typicode.com';
  var p = [];

  p.push( $.ajax({url: root + '/posts/1', method: 'GET'}));
  p.push( $.ajax({url: root + '/posts/2', method: 'GET'}));
  p.push( $.ajax({url: root + '/posts/3', method: 'GET'}));
  p.push( $.ajax({url: root + '/posts/4', method: 'GET'}));

  Promise.all(p).then(values => { 
    console.log( 'Ajax responses after they have all finished: ', values); 
  });

See this plnkr for an exemple.

Hope this help !

Clement
  • 3,860
  • 4
  • 24
  • 36
  • Good use of Promise.all. With an array of URLs, you can do somethings like that: const loadUrls = async urls => { let results = []; urls.forEach(url => { results.push($.ajax({url})); }) return await Promise.all(results); } – Synn Oct 14 '18 at 12:57
3

You can achieve this by also using $.when. You just need to store all the AJAX requests you make in an array and apply() that array to $.when. Try this:

$.when(ajax1).done(function() {
    var requests = [];
    for (i = 0; i < array.length; ++i) {
        requests.push($.ajax({
            url: 'anotherurl?=' + myarray[i],
            dataType: "JSONP",
            success: function (data) {
                // do stuff here
            }
        }));
    }
    $.when.apply($, requests).done(function() {
        console.log('complete');
    });
})

You can also shorten the logic slightly by using map(), although be aware this won't work in < IE9.

$.when(ajax1).done(function() {
    var requests = array.map(function() {
        return $.ajax({
            url: 'anotherurl?=' + myarray[i],
            dataType: "JSONP",
            success: function (data) {
                // do stuff here
            }
        });
    });
    $.when.apply($, requests).done(function() {
        console.log('complete');
    });
})
Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
0

jQuery is going to rear its stubborn head pretty quickly here. I'd recommend you reach for something better like Promises that give you more control in this type of situation

const pajax = opts=>
  new Promise((resolve, reject)=>
    $.ajax(opts).done(x => resolve(x)).fail((_,_,err)=> reject(err))

Then you could use it like this with Promise.all

pajax({
  url: 'myurl.php',
  type: "GET",
  dataType: "jsonp",
})
.then(data => {
  // create your arr
  let arr = ...

  return Promise.all(arr.map(x=> {
    return pajax({
     url: 'anotherurl?=' + x,
     type: "GET",
     dataType: "jsonp"
    })
  }))
})
.then(data => {
  console.log('this is called after all promises are done'
})
.catch(err=> {
  console.error(err)
})

EDIT

@RoryMcCrossan's answer is nice if you want to keep everything in the jQuery realm

Mulan
  • 129,518
  • 31
  • 228
  • 259