【问题标题】:Angularjs - $q.all not holding the promises in an sync wayAngularjs - $q.all 没有以同步的方式持有承诺
【发布时间】:2014-12-18 14:00:31
【问题描述】:

我想使用 $q.all 来等待函数完成。我在 plunker 中有一个例子@987654321@

<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 的 sync。全部。不能改变 xxy 函数的性质,因为它会破坏我的大项目中的其他东西。 xxy() 是我正在使用的一个大函数的简单版本,它使用 $q.defer 构建。

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

【问题讨论】:

  • plunker or fiddle please

标签: javascript angularjs


【解决方案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 来演示异步行为并能够将promise 解析到它所属的回调中。

希望我正确理解了您的问题。

【讨论】:

  • 我看到了,repeater基本是递归函数,把$scope换成普通函数,这样angularjs范围检查就不会触发了。确实解决了我在某种程度上遇到的问题。谢谢。
【解决方案2】:

问题出在你的运行函数中......你目前已经把这个注释掉了......

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

但是 $q.all 解析了一个结果数组(按照 promise 传入的顺序,所以你需要使用这个...

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

编辑这里它在更新的plnkr中工作

来自文档 (link) 将多个 Promise 组合成一个 Promise,当所有输入 Promise 都已解决时,该 Promise 将被解决。 返回: 一个数组或 promise 的散列。

【讨论】:

  • 我想要的输出是 1 20 2 40 ...当前输出是 1 2 .. 20 40。我想将 xxy 函数用作同步调用,但我无法更改核心我项目中的 xxy 函数,因为它太大并且可能会破坏其他一些东西。
【解决方案3】:

$scope.xxy(i) 返回一个承诺

您不能只是循环并等待返回值。承诺不会那样工作。

相反,您必须这样做。

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

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

【讨论】:

  • 那么,我该怎么做才能使返回承诺的函数等到它完成一些代码,然后正常继续。基本上我需要以某种方式欺骗异步函数同步。
猜你喜欢
  • 2014-02-02
  • 1970-01-01
  • 1970-01-01
  • 2018-01-31
  • 1970-01-01
  • 1970-01-01
  • 2016-02-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多