Promise .then() 在 for 循环内按顺序运行

问题描述 投票:0回答:1

我正在尝试通过多个连续的 API 调用来依次填充我的

$scope.results = []
。顺序很重要,因为我传递了一个开始和一个限制数字(类似于分页)。有一个原因是我无法在 1 次调用中完成此操作,并且需要中断多个调用,因为 API 网关在 30 秒后超时。

我的问题是在 for 循环中它不能按顺序工作。在数组内部,所有网络请求似乎都获得相同的

start
值,并且不是按顺序发送的。我也无法使用
async/await
。有没有办法按顺序运行 API 调用并将结果添加到
results
数组中。我的最终目标是像在单个 API 调用中发生的那样填充数组,但需要多次调用

         $scope.detailedReportOfAll = function () {
            $scope.start = 0;
            $scope.limit = 15;
            $scope.results = [];
            var requestCount = 1;
            APIService.getDetailedReportData($scope.start,$scope.limit).then(
              function ({result,nbPages}) {
                if (result.length){
                  $scope.results = $scope.results.concat(result);
                  requestCount ++;
                  $scope.start += $scope.limit;
                }
                if (requestCount < nbPages){ //I'm running the loop for (nbPages - 1) times

                  for (i=2; i<nbPages; i++){
                    APIService.getDetailedReportData($scope.start,$scope.limit).then(
                      function ({result,nbPages}) {
                        if (result.length){
                          $scope.results = $scope.results.concat(result);
                          requestCount ++;
                          console.log($scope.results, requestCount)
                          $scope.start += $scope.limit;
                        }
                      })
                  }
                }
              }
            );
          };

这是我的http调用函数。它返回一个承诺:

    var getDetailedReportData= function (start, limit) {
      $rootScope.isLoading = true;
      var deferred = $q.defer();
      $http
        .get(rootURL('/getAllReports/'+start+'/'+limit))
        .success(function (response) {
          deferred.resolve(response);
        })
        .catch(function (err) {
          deferred.reject(err);
        })
        .finally(function () {
          $rootScope.isLoading = false;
        });
      return deferred.promise;
    };
javascript angularjs promise
1个回答
2
投票

如果你想连续运行这些,那么当你知道异步函数n-1完成时,你需要触发异步函数n;即在

then
回调中。如果您拒绝了
async
await
,那么递归调用函数可能是最简单的方法。

function somethingAsync(value) {
    return new Promise(res => setTimeout(res, 500, value * value));
}

function processInputInSeries(input) {
    function processNext(index, input, results) {
        if (index >= input.length) return results;
        return somethingAsync(input[index]).then(function (result) {
            return processNext(index + 1, input, [...results, result]);
        });
    }

    return processNext(0, input, []);
}

const resultPromise = processInputInSeries([1,2,3]);
resultPromise.then(function(results) { console.log(results) });

作为比较,

async
/
await
更清晰:

function somethingAsync(value) {
    return new Promise(res => setTimeout(res, 500, value * value));
}

async function processInputInSeries(input) {
    let results = [];
    for (let i = 0; i < input.length; i++) {
        const result = await somethingAsync(input[i]);
        results = [...results, result];
    }
    return results;
}

const resultPromise = processInputInSeries([1,2,3]);
resultPromise.then(function(results) { console.log(results) });

即使你最终使用 Babel 来转译你的 JS 以与过时的系统兼容,我也建议你这样写。

© www.soinside.com 2019 - 2024. All rights reserved.