AngularJS $ q.all()结果为null

时间:2014-02-14 11:11:54

标签: javascript angularjs q

我正在尝试实现一个$ q.all来运行一些函数,然后将所有输出返回到最后附加到.then的函数中。

目前承诺看起来他们正在以正确的顺序调用而$ all .then正在最后发生,但结果变量返回一个空数组($ q中的每个承诺一个) 。所有)

JS Fiddle可以在http://jsfiddle.net/QqKuk/120/找到,我正在使用角度1.0.1

以下是我所拥有的代码的简化示例。

这是我的html,只是在那里显示一些调试文本和输出。

<div ng-controller="MyCtrl">
    <p>{{fromThen}}</p>
    <p>{{fromThen2}}</p>
    <p>{{runOrder}}</p>
</div>

这是我的控制器,实际上logOne,logTwo和logThree不会是相同的功能。

var myApp = angular.module('myApp',[]);

函数MyCtrl($ scope,$ q,$ timeout){

var logOne = function (value) {
    $scope.fromThen = $scope.fromThen + value;
    var deffered = $q.defer();
    deffered.promise.then( function() {
            $scope.runOrder = $scope.runOrder + '.logOne()';
            $scope.fromThen = $scope.fromThen + value.toUpperCase();
            deffered.resolve(value);
            return deffered.promise;
    });

    deffered.resolve();
};

var logTwo = function (value) {
    $scope.fromThen = $scope.fromThen + value;
    var deffered = $q.defer();
    deffered.promise.then( function() {
            $scope.runOrder = $scope.runOrder + '.logTwo()';
            $scope.fromThen = $scope.fromThen + value.toUpperCase();
            deffered.resolve(value);
            return deffered.promise;
    });

    deffered.resolve();
};

var logThree = function (value) {
    $scope.fromThen = $scope.fromThen + value;
    var deffered = $q.defer();
    deffered.promise.then( function() {
            $scope.runOrder = $scope.runOrder + '.logThree()';
            $scope.fromThen = $scope.fromThen + value.toUpperCase();
            deffered.resolve(value);
            return deffered.promise;
    });

    deffered.resolve();
};


$scope.fromThen = '';
$scope.fromThen2 = 'No Value';
$scope.runOrder = '';


$q.all([logOne('One'), logTwo('Two'), logThree('Three')])
                    .then(function(results) {
                        $scope.runOrder = $scope.runOrder + '.then';
                        $scope.fromThen2 = results;
                    });

}

我得到的输出是

OneTwoThreeONETWOTHREE [NULL,NULL,NULL] .logOne()。logTwo()。logThree()。​​然后

对我来说,看起来事情正在以正确的顺序调用,所以我很困惑为什么我在返回值中得到空值。我是否错误地使用了defer.resolve(value)?

我在这里看了一些其他的例子,但是我无法弄清楚为什么我没有得到结果。

感谢您提供任何帮助。由于这也是我的第一篇文章,任何有关我应该包括(或不需要包括)的信息的提示也将不胜感激。

感谢。 尼尔

1 个答案:

答案 0 :(得分:2)

您的问题是,您没有从日志功能本身返回您的承诺,以便跟随$q.all。你正在解决这些承诺并将它们归还给某个地方,但不是在任何正在倾听的地方。调用.then内部的函数由$q调用,返回值将发送到promises .then本身返回的解析回调。您有希望的功能应采取以下形式:

var function = doSomthingDeferred(data) {
  var deferred = $q.defer();
  doSomethingDeferredWith(data).then(function(deferredResult) {
    var processedResult = processDeferredResult(deferredResult);
    deferred.resolve(processedResult);
  });
  return deferred.promise;
}

替代地

var function = doSomthingDeferred(data) {
  return doSomethingDeferredWith(data).then(function(deferredResult) {
    var processedResult = processDeferredResult(deferredResult);
    return processedResult;
  });
}

在您的情况下,当您doSomethingDeferredWith(data)时:

function doSomethingDeferredWith(data) {
  var deferredMore = $q.defer();
  $scope.fromThen += data;
  deferredMore.resolve($scope.fromThen);

此特定操作并非真正需要延迟,它会立即结束,但如果您要查询基于$http的服务,那么您将获得{{1}承诺回来:

deferredMore

然后,在完成此操作之后,您将获得一些结果作为 return deferredMore.promise; } .then调用中引用的函数的参数,就像从promise返回的函数一样。 {1}}:

doSomethingDeferredWith

现在,由于doSomethingDeferredWith(data).then(function(deferredResult) { 的工作方式,对$q的调用会返回一个承诺,在该承诺上调用doSomethingDeferredWith(data),传入的函数排队,但在当前脚本循环结束之前不会执行。这意味着调用.then,函数排队,然后.then继续执行,返回,然后其调用函数继续执行,直到调用堆栈清除为止。只有在那之后,doSomethingDeferred才有机会回来并运行已解决的承诺的所有回调。

在您的代码$q中,各种doSomethingDeferred函数实际上不会返回承诺。他们返回log***。如果您返回我们创建的承诺,并且会在undefined运行回调而不是$q结束时解决,您将在doSomethingDeferred的回调中获取数据。

要修复代码,请将每个日志文件末尾的$q.all次调用更改为deffered.resolve();然后,日志函数的返回值将不是return deffered.promise;,它们将成为undefined可以遵循的承诺,并在完成所有三次调用后立即对其所有三个$q来电进行回调,将.resolve值设置为$scope.runFrom2数组{1}}因为每个单独的承诺都使用推迟函数的闭包框架中的['One','Two','Three']解析。

  

tl;博士版

     

将每个日志文件末尾的value次来电更改为deffered.resolve();