0

I have the following code that has a list, and for every element in this list, do an ajax call.

util.testMethod = function(list) {

            var map = new Map();

            list.forEach(function(data) {
                $.ajax({
                    url: 'https://......',
                    type: 'GET',
                    data: // data needed here
                    success: function(data) {
                        // do something
                    },
                    error: function(jqxhr, settings, exception) {
                        // dos omething
                    }
                });
            });


            return map;
        };

Since I am making a number async ajax calls, let's assume there is 1 of them takes so long to execute. Is there a possibility that this testMethod will return before that ajax call finish?

Haobo_X
  • 77
  • 1
  • 8

1 Answers1

2

Definitely. The ajax call is asynchronous so the code will continue to execute without waiting for the success/error callback functions.

You have two options:

  1. Make your ajax call as a synchronous call (more info here)
  2. (recomended) Make your testMethod functions an async function (more info here)

But (1º option):

Setting async property to false is deprecated and in the process of being removed (link). Many browsers including Firefox and Chrome have already started to print a warning in the console if you use this:

And follows an example for the 2º Option (more about javascript promises in here and Promise.All in here):

async function makeAjaxCall()  {
    return new Promise((resolve) => {
        setTimeout(() => {
            // Just to make the makeAjaxCall 1 second slower;
            $.ajax({
                url: 'http://www.mocky.io/v2/5e6ac7d32d0000db0c5fa686',
                type: 'GET',
                data: {},
                success: function(data) {
                    resolve(data);
                },
                error: function(jqxhr, settings, exception) {

                     resolve({ error: 'OMG an ERROR!'});
                    // dos omething
                }
            })
        }, 1000);
    });      
};

async function asynCall() {
  for(let i=0; i<10; i++) {
      // You can see in here that will wait 1 second before is going to the next ajax call
      const result = await makeAjaxCall();
      console.log(result);
  }
}

// You can run all your calls in paralel by using the Promise.All like this
async function promiseAll() {
  const ajaxCalls = [];
  for(let i=0; i<10; i++) {
      ajaxCalls.push(makeAjaxCall());
  }
  
  //for this case, the calls will be made in parallel, which measn will take slight more than 1 second 
  Promise.all(ajaxCalls).then(function(values) {
    // will print the array of values which contains the values of each ajax call
    console.log(values);
  });
}

asynCall();
promiseAll();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Ricardo Rocha
  • 14,612
  • 20
  • 74
  • 130
  • 1
    Option #1 is definitely not recommended and may not even be possible with modern browsers – Phil Mar 12 '20 at 23:29
  • Is there a way to force the function to wait for all ajax calls to finish before return? It seems I can use something like $.when, but that only applies to a fix number of promises. But in my case, the number of promises will be the same as my list size. – Haobo_X Mar 12 '20 at 23:43
  • @Haobo_X I made changes to my code. I hope such changes will answer to all your doubts. – Ricardo Rocha Mar 13 '20 at 00:01