在 for 循环中按顺序承诺 .then() 到 运行

promise .then() to run sequentially inside a for loop

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

我的问题是 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调用函数。它returns一个承诺

    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;
    };

非常感谢帮助

如果你想运行这些串联,那么当你知道异步函数n-1[时,你需要触发异步函数n =37=]完成;即在 then 回调中。如果您拒绝 asyncawait.

,递归调用函数可能是最简单的方法

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 以与过时的系统兼容,我也建议您这样写。