【发布时间】:2017-11-28 10:26:14
【问题描述】:
我有一个示例代码,其中有一个 for 循环,其中有一个函数可以调用 ajax 来获取数据。我在这里面临一个问题,我需要在完成ajax 调用后才进行迭代。正在发生的事情是迭代正在完成,甚至循环之后的语句也正在执行,然后ajax 调用才完成。
实际结果 - 循环 1 启动, 循环 1 完成, 循环执行之外的语句, Ajax 调用完成。
预期结果 - 循环 1 启动, Ajax 调用完成, 循环 1 完成, 循环执行之外的语句。
我们可以在以下示例代码的输出中看到 $scope.finalData 的值是空的,因为数据分配发生在 ajax 调用完成之前。
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="customersCtrl">
<ul>
<li ng-repeat="x in finalData">
{{ x.Name + ', ' + x.Country }}
</li>
</ul>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('customersCtrl', function($scope, $http) {
$scope.myData = [];
for(var i=0;i<5;i++){
console.log('before '+i+'execution');
$http.get("https://www.w3schools.com/angular/customers.php").then(function (response) {
$scope.myData = response.data.records;
console.log('Inside loop - data'+response.data.records);
});
console.log('Outside loop - data'+$scope.myData);
console.log('after '+i+'execution');
}
$scope.finalData = $scope.myData;
});
</script>
</body>
</html>
我还更新了 plunker 中的代码 - https://plnkr.co/edit/XyRVeY5WuUT6ZEKOjc2M?p=preview
【问题讨论】:
-
$http是一个异步回调,你不能指望它会在你的日志之间到达。您可以在$http.get(...).then(/* here */).finally(/* or here */)中进行所有处理。如果您想进行多次$http调用,请使用$q作为:$q.all(promises),并附加promises.push($http.get(...).then( return ...; )) -
解决方案是根本不使用循环。自己维护
i作为柜台。当 i = 0 进行第一个 ajax 调用。然后当该调用完成时,将 i 增加到 1 并进行下一次调用,等等,直到你完成。显然,您需要将调用的代码封装在一个函数中,该函数接受i(以及它需要的任何其他参数)作为输入参数,否则您将大量重复您的代码。 -
@Alexksey Solovey 是的,实际上已经尝试过了。这只是我实际问题的一个说明。考虑我们需要遍历一个数组并将值作为查询字符串发送。我可以使用 $q.all(promises)。但是我需要在 for 循环之外执行一些其他独立语句,以便仅在 for 循环完成后执行,这应该仅在 ajax 调用后完成。
-
$q.allis 在 for 循环之外,您可以使用以下命令检索结果(全部):$q.all(promises).then((res) => { $scope.finalData = res; }).finally( /* any other asynchronous processing goes here */ );