Ajax API calls in loop need to be executed in orde

2019-04-17 10:06发布

lets say you have a scenario where you needed to create a .csv output in a page's textarea...

So I have an array of queries which i loop. Inside the loop im passing a query to an ajax call... I need to append the result of the ajax call into the textarea.

My question is how do you get the results printed out in the order they are requested (basically the order in the queries array)

//example array to loop.
var queries= ['query1', 'query', 'query3', 'query4'];

//the textarea where im going to print the results in order later to open in excel as a .csv file
var $csvText= $('#some-text-area');

//inserting the csv headers
$csvText.val('Column1, Column2\r\n');

$.each(queries, function(index, value){
   //someGoogleAPI is an ajax call from google's api
   someGoogleAPI(value).then(function(response){
      //Adding row with values
      $csvText.val(response.column1 + ',' response.column2 + '\r\n');
   });
})

This is simplified example but by resolving this I would get an idea of how to tackle my problem.

Thanks guys.

2条回答
Bombasti
2楼-- · 2019-04-17 10:58

Instead of $.each you can use reduce to create an arbitrary list of promises.

queries.reduce(function(seq, val) {
    return seq.then(function() {
      return someGoogleAPI(val)
    })
    .then(function(response){
        var curr = $csvText.val();
        $csvText.val(curr + ',' + response.column1 + ',' + response.column2 + '\r\n');
      });
}, Promise.resolve());

jsfiddle: https://jsfiddle.net/75sse6n2/

查看更多
小情绪 Triste *
3楼-- · 2019-04-17 11:03

It appears that your queries do not depend upon each other and thus can be executed in parallel. If that's the case, then you really just need to get the responses processed in order. You can do that several ways:

Run in Parallel with Promise.all()

Launch all the requests in parallel, collect all the results, use Promise.all() to know when they are all done and then insert all the results.

//example array to loop.
var queries= ['query1', 'query', 'query3', 'query4'];

//the textarea where im going to print the results in order later to open in excel as a .csv file
var $csvText= $('#some-text-area');

//inserting the csv headers
$csvText.val('Column1, Column2\r\n');

Promise.all(queries.map(function(item) {
   return someGoogleAPI(value);
})).then(function(results) {
   $csvText.append(results.map(function(item) {
        return response.column1 + ',' response.column2;
   }).join('\r\n'));       
});

Promise.all() will collect the results in order, regardless of which requests actually finished first.

Sequence Your Operations

You can sequence your operations so only one is run at a time, it's result is inserted, then the next one is run and so on. This will be a slower end-to-end run time, but gives you intermediate display of results.

//example array to loop.
var queries= ['query1', 'query', 'query3', 'query4'];

//the textarea where im going to print the results in order later to open in excel as a .csv file
var $csvText= $('#some-text-area');

//inserting the csv headers
$csvText.val('Column1, Column2\r\n');

queries.reduce(function(p, item) {
    return p.then(function() {
        return someGoogleAPI(item).then(function(result) {
            $csvText.append(result.column1 + ',' result.column2 + '\r\n');
        });
    });
}, Promise.resolve());

This will create a series of chained promises that will execute in order, one after the other which each one inserting its result when it arrives.

查看更多
登录 后发表回答