Angularjs - $ q.all没有以同步的方式持有承诺

时间:2014-12-18 14:00:32

标签: javascript angularjs

我想使用$ q.all来等待函数完成。我在plunker http://plnkr.co/edit/uG2JujPqoiBgqtRjEZwh?p=preview

中有一个例子
<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.min.js"></script>
</head>
<body ng-app="App">
    <div ng-controller="AppController">
        Its the app
        <button ng-click="run()">Run (check console)</button>
    </div>

    <script>
    var App = angular.module("App", []);
    App.controller("AppController", function($scope,$q){

        $scope.xxy = function(num){
            var d = $q.defer();
            for(var i=0;i<100000;i++){
                //do nohing
            }
            d.resolve(num*20);

            var promise = d.promise;

            return $q.all([promise]).then(function(data){
                return data;
            });

        };

        $scope.run = function(){
            for(var i=0;i<10;i++){
                console.log(i);
                console.log($scope.xxy(i));
                //$scope.xxy(i).then(function(r){
                //    console.log(r);
                //})
            }    
        };
    });

    </script>
</body>
</html>

函数 xxy()是以 async 方式编写的,但我希望它使用$ q 同步。所有。不能改变xxy函数的性质,因为它会破坏我的大项目中的其他东西。 xxy()是我正在使用的一个大函数的简单版本,并使用$ q.defer构建它。

所以基本上我希望输出为:1 20 2 40 ...而不是当前的1 2 .. 20 40 ......

3 个答案:

答案 0 :(得分:1)

问题在于你的跑步功能....你现在已经注释掉了....

$scope.xxy(i).then(function(r){
  console.log(r);
})

但$ q.all解析了一系列结果(按照承诺的传递顺序排列,所以你需要使用它...

$scope.xxy(i).then(function(r){
  console.log(r[0]); // first item of the result array
})

编辑此处处于更新的plnkr

来自文档link) 将多个promise组合成一个promise,在解析所有输入promise时解析。 返回:承诺的数组或散列。

答案 1 :(得分:1)

所以,你想要序列化行为:打印1,调用异步函数并打印返回值20,然后再次运行循环,打印2,然后调用异步函数,依此类推?

这确实是一个有趣的问题。对我而言,您似乎需要使用repeater pattern

适用于您的案件:

App.controller("AppController", function($scope,$q,$timeout) {

    $scope.xxy = function(num) {
        var d = $q.defer();

        $timeout(function() {
            d.resolve(num*20);
        }, 1000);

        return d.promise;
    };

    $scope.repeater = function(i)  {
        if (i < 10) {
            console.log(i);
            $scope.xxy(i).then(function(ret) {
                console.log(ret);
                $scope.repeater(i + 1);
            });
        }
    };

    $scope.run = function() {
        $scope.repeater(0);
    };
});

请参阅操作:JSFiddle

我添加$timeout来演示异步行为,并能够将承诺解析为它所属的回调。

我希望我能正确理解你的问题。

答案 2 :(得分:0)

$scope.xxy(i)会返回承诺

您无法循环并等待返回值。承诺不会那样工作。

相反,你必须这样做。

$scope.xxy(num).then(function(value){
      ...
});

$q.all(..)将数组中的所有承诺包装成新的承诺。