我正在尝试通过多个连续的 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;
};
如果你想连续运行这些,那么当你知道异步函数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 以与过时的系统兼容,我也建议你这样写。