1

I'm having some problems with the ajax async. I have an array then loop through the array to make an ajax call, if success the ajax will return an xml string, i'll use it to fill in an table and update process bar. I use async:false it works fine on Firefox, but it's not work properly on Chrome. I also tried to use $.ajax().done(), but it's not affect at all.

Is there anyway to get the responsed xml string when ajax call finish then the next loop will run?

for (var i = 0; i <= arr.length; i++){
    $.ajax({
        url: '',
        data: '',
        async: false
    }).done(function(xml) {
       //get xml string to handle and put it into some table as contents
    });
    //Then go to next loop
}
Steven Dang
  • 182
  • 1
  • 12
  • 3
    Truly synchonous AJAX is deprecated, and for good reason. Nothing should ever block the UI thread. Read into `async`/`await` and `await` the call. Note that [it still won't be synchronous, and will never be, and you need to adjust the remaining code accordingly](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call). – CherryDT Aug 05 '20 at 08:09
  • Using `await` here is distinctly suboptimal: There's no dependency of request 2 on request 1 so running them serially instead of in parallel will just be slow. – Quentin Aug 05 '20 at 08:23
  • I have tried using async/await, and it's really helpful to solve my problem. Thanks so much @CherryDT – Steven Dang Aug 06 '20 at 06:47

3 Answers3

5

Don't try to make asynchronous code synchronous. You will lock up the event loop and get a nasty performance penalty.

Make the requests in parallel. Collect the promises in an array. Use Promise.all to determine when they have all completed.

Then you can extract the data from them and do what you will with it.

For example:

const baseUrl = "https://jsonplaceholder.typicode.com/users/";
const userIds = [1,2,3,4,5];

const completeUrls = userIds.map( id => `${baseUrl}${id}` );
const promises = completeUrls.map( url => jQuery.ajax({url}) );
const collectedDataPromise = Promise.all(promises);

collectedDataPromise.then( data => {
    const names = data.map( user => user.name );
    const ul = $("<ul />");
    names.forEach( name => {
       ul.append( $("<li>").text(name) );
    });
    $("body").append(ul);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
-1

If you have to update data in each iteration, you can use some string and update in in .done().

Try it with recursion like this:

var counter = arr.length;

function callAjax() {
  if (counter) {
    $.ajax({
      url: '',
      data: ''
    })
    .done(function(xml) {
      //get xml string to handle and put it into some table as contents
      counter--;
      callAjax();
    });
  }
}
Pranav Rustagi
  • 2,604
  • 1
  • 5
  • 18
-1

Finally, i got my own solution that i use the async/await to make sense.

async function ajaxGetData(){
    return $.ajax({
               url: '',
               data: ''
          }).then(response => response.data);
}

async function hanldeResponse(){
   var arr = [1,2,...];
   for(var i = 0; i < arr.length; i++){
       let res = await ajaxGetData();
       //some code to handle the response with res variable
   }
}
Steven Dang
  • 182
  • 1
  • 12