嵌套循环中的Ajax API调用需要按

时间:2016-06-25 16:23:08

标签: javascript jquery ajax promise jquery-deferred

假设您有一个场景,您需要在页面的textarea中创建.csv输出...

所以我有2个数组,我循环嵌套在一起。嵌套循环的结果是传递ajax调用的查询...我需要将ajax调用的结果附加到textarea中。

我的问题是如何按照请求的顺序打印结果(基本上是查询数组中的顺序)



//example array to loop.
var outerQuery= ['A', 'B', 'C', 'D', 'E', 'F'];
var outerQueryLegth = outerQuery.length;
var innerQuery= ['1', '2', '3', '4', '5', '6'];
var innerQueryLegth = innerQuery.length;

//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');

//outter loop
$.each(outerQuery, function(outerIndex, outer){
      //Print the row
      $csvText.append('Row' + outer +'\r\n\r\n');
      
      //Nested inner loop (that should execute in order regarless or the time of the api call)
      innerQuery.reduce(function(innerCallback, inner, innerIndex){
        return innerCallback.then(function(){
        	return GoogleAnalyticsAPI(inner).then(function(response){
            $csvText.append(response.column1 +',');
          });
        });//end inner callback
      },Promise.resolve());
});

function GoogleAnalyticsAPI(val) {
	return new Promise(function(resolve) {
    setTimeout(function() {
      resolve({column1: val });
    }, Math.floor((Math.random() * 1000) + 1));
  });
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<textarea id="some-text-area" rows="20" cols="30"></textarea>
&#13;
&#13;
&#13;

正如你所看到的那样,片段中的结果非常糟糕 理想情况下,他们应该这样打印:

RowA
1,2,3,4,5,6
RowB
1,2,3,4,5,6
RowC
1,2,3,4,5,6
.
.
.

我从Ajax API calls in loop need to be executed in order得到的innerQuery.reduce非常感谢@ jfriend00

谢谢你们

2 个答案:

答案 0 :(得分:1)

您可以使用.queue().promise()按顺序返回与数组中索引相对应的函数

&#13;
&#13;
//example array to loop.
var outerQuery = ['A', 'B', 'C', 'D', 'E', 'F'];
var outerQueryLegth = outerQuery.length;
var innerQuery = ['1', '2', '3', '4', '5', '6'];
var innerQueryLegth = innerQuery.length;
var $csvText = $('#some-text-area');

// create `"outerQuery"` queue
$csvText.queue("outerQuery", $.map(outerQuery, function(outer, index) {
  return function(next) {
    $(this).append((index > 0 ? '\r\n\r\n' : "") 
                    + 'Row' + outer + '\r\n\r\n')
    // create `"innerQuery"` queue
    .queue("innerQueue", $.map(innerQuery, function(inner, innerIndex) {
        return function(_next) {
          return GoogleAnalyticsAPI(inner).then(function(response) {
            $csvText.append(response.column1 + ',');
            // call `_next` function in `"innerQueue"`
          }).then(_next); 
        }
      })).dequeue("innerQueue").promise("innerQueue")
    // call `next` function in `"outerQueue"`
    // when all functions in current `innerIndex`
    // of `innerQueue` array , `"innerQueue"` completes
    .then(next)
  }
})).dequeue("outerQuery");

function GoogleAnalyticsAPI(val) {
  return new Promise(function(resolve) {
    setTimeout(function() {
      resolve({
        column1: val
      });
    }, Math.floor((Math.random() * 1000) + 1));
  });
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<textarea id="some-text-area" rows="20" cols="30"></textarea>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

您可以继续使用this prior answer中内部.reduce()循环所使用的相同逻辑,并将其应用于外循环。此外,您可以使用普通的Javascript概念进行此同步。

这样做的关键是来自先前答案的内部.reduce()循环返回一个仅在内循环中的所有链式异步操作完成时才解决的promise。您可以使用该承诺来控制和同步外部循环,如下所示:

&#13;
&#13;
//example array to loop.
var outerQuery= ['A', 'B', 'C', 'D', 'E', 'F'];
var innerQuery= ['1', '2', '3', '4', '5', '6'];

//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');

//outer loop
outerQuery.reduce(function(outerP, outerItem) {
    return outerP.then(function() {
        //Print the row
        $csvText.append('Row' + outerItem +'\r\n');
        return innerQuery.reduce(function(innerP, inner, innerIndex){
            return innerP.then(function(){
                return GoogleAnalyticsAPI(inner).then(function(response){
                $csvText.append(response.column1 +',');
              });
            });
        }, Promise.resolve()).then(function() {
            $csvText.append('\r\n\r\n');
        });      
    });
}, Promise.resolve());

function GoogleAnalyticsAPI(val) {
	return new Promise(function(resolve) {
    setTimeout(function() {
      resolve({column1: val });
    }, Math.floor((Math.random() * 500) + 1));
  });
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<textarea id="some-text-area" rows="20" cols="30"></textarea>
&#13;
&#13;
&#13;