snazzybouche
snazzybouche

Reputation: 2427

How to wait for an ajax call to finish before moving on to the next?

I have a situation where I need to make multiple ajax requests. The URLs that I need to access are contained as strings in the listOfUrls array.

What I'd like to do is make one ajax request, process it, feed the data back into my application, and then move onto the next one.

A basic version of the code I've got at the minute is this

var fetch = function(url) {
  $.get(url, function(response) {
    // do stuff with the data
  };
  return someData;
};

for(let i = 0; i < listOfUrls.length; i++) {
  fetch(listOfUrls[i]);
  console.log("Fetching " + listOfUrls);
};

// do more stuff after all requests are finished

The issue here is that these are asynchronous requests, and while I could potentially just use synchronous requests I don't really want to risk that - and then I wouldn't be able to use the console.log within the loop, because the browser would hang.

What I'd prefer to do is use a promise to iterate through the loop:

var fetch = function(url) {
  $.get(url, function(response) {
    // do stuff with the data
  };
  return someData;
};

for(let i = 0; i < listOfUrls.length; i++) {
  fetch(listOfUrls[i]).done( /* move onto the next one */ ).fail( /* throw an error */ );
  console.log("Fetching " + listOfUrls);
};

// do more stuff after all requests are finished

Promises obviously can't force an iteration through the for loop.

How would I go about implementing this behaviour?

Upvotes: 2

Views: 368

Answers (1)

Rory McCrossan
Rory McCrossan

Reputation: 337560

You can use recursion to call the next URL on the successful completion of the previous one.

If I wanted fetch() to also return data back to the part of the script that called it, how would I do that?

As all the requests are asynchronous you cannot return anything. To do what you require you could populate an array with the data retrieved from all the requests, then provide that to another function which you call when all requests have completed, something like this:

var obj = [];

function makeRequest(index) {
  $.get(listOfUrls[index || 0], function(response) {
    // do stuff with the response
    obj.push(response);

    if (++index < listOfUrls.length) {
      makeRequest(index);
    } else {
      finaliseRequests(obj);
    }
  });
}

function finaliseRequests(data) {
  // work with all the received data here...
}

makeRequest(); // onload

Upvotes: 2

Related Questions