首页 文章

AngularJS $ q.all()结果为null

提问于
浏览
0

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

在承诺看起来他们正在以正确的顺序调用并且$ all . 然后在结束时发生,但结果变量返回一个空数组($ q.all中的每个承诺一个)

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',[]);

function 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 回答

  • 2

    您的问题是,您没有从日志功能本身返回您的承诺,以便跟随 $q.all . 你're resolving the promises and returning them somewhere, but not to anywhere that'正在听 . 调用 .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 的服务,那么你将得到你的 deferredMore 承诺:

    return deferredMore.promise;
    }
    

    然后,在're done doing that, you'之后,将某个结果作为参数传递给 .then.then 调用中引用的函数,就像从 doSomethingDeferredWith 返回的那样:

    doSomethingDeferredWith(data).then(function(deferredResult) {
    

    现在,由于 $q 的工作方式,对 doSomethingDeferredWith(data) 的调用返回一个promise, .then 在该promise上调用,传入的函数排队, but is not executed until the current script loop ends . 这意味着调用 .then ,函数排队,然后 doSomethingDeferred 继续执行,返回,然后其调用函数继续执行,直到调用堆栈清除为止 . 只有在那之后 $q 才有机会回来并运行已解决的承诺的所有回调 .

    在你的代码 doSomethingDeferred 中,各种 log*** 函数实际上并没有返回一个promise . 他们返回 undefined . 如果您返回我们创建的承诺,并且当 $q 运行回调而不是 doSomethingDeferred 结束时将解析,您将在 $q.all 的回调中获取数据 .

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

    tl; dr Version更改deffered.resolve();在每个日志文件的末尾调用以返回deffered.promise;

相关问题