【问题标题】:How to iterate through the 'For' loop only after completion of ajax calls in angularjs?仅在 angularjs 中完成 ajax 调用后,如何遍历“For”循环?
【发布时间】: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.all is 在 for 循环之外,您可以使用以下命令检索结果(全部):$q.all(promises).then((res) =&gt; { $scope.finalData = res; }).finally( /* any other asynchronous processing goes here */ );

标签: angularjs ajax for-loop


【解决方案1】:

这里的问题是您期望异步调用(ajax 请求)以同步方式运行(暂停直到完成)。实际发生的是 $http.get 立即 返回一个承诺,并且您的 for 循环继续完成,没有延迟。随后,承诺最终会在所有同步代码完成后 解决,从而导致您描述的不希望的执行顺序。

也许考虑另一种方法,您首先使用循环(或map)生成一个promise列表(每个代表一个单独的ajax请求),然后使用$q.all确保它们在进一步执行之前全部解决(如here 所示)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-27
    • 1970-01-01
    • 2018-07-04
    • 2020-11-17
    • 1970-01-01
    • 1970-01-01
    • 2014-11-11
    相关资源
    最近更新 更多