javascript - AngularJS $q.all() 结果为空

标签 javascript angularjs q

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

目前,promise 看起来像是按照正确的顺序调用的,并且 $all .then 发生在最后,但是 results 变量返回了一组 null 值($q 中的每个 Promise 都有一个空值) .全部)

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

下面是我的代码的简化示例。

这是我的 html,只是用来显示一些调试文本和输出。

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

这是我的 Controller ,实际上 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;
                    });

}

我得到的输出是

一二三一二三 [空,空,空] .logOne().logTwo().logThree().then

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

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

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

谢谢。 尼尔

最佳答案

您的问题是您没有从日志函数本身返回您的 promise 以供 $q.all 遵循。你正在解决 promise 并将它们返回到某个地方,但不是返回到正在监听的任何地方。对 .then 的调用内部的函数由 $q 调用,并且返回值被发送到 .then 本身返回的 promise 的解析回调。您有希望的功能应采用以下形式:

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 promise :

  return deferredMore.promise;
}

然后,完成此操作后,您将获得一些结果,作为在 .then 上调用 promise 时引用的函数的参数,就像从 doSomethingDeferredWith 返回的函数一样:

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

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

在您的代码 doSomethingDeferred 中,各种 log*** 函数实际上并不返回 promise 。他们返回 undefined 。如果您返回我们创建的 Promise,并将在 $q 运行回调时解析,而不是在 doSomethingDeferred 结束时解析,那么您将在 $q.all 的回调中获取数据。

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

tl;dr Version

Change the deffered.resolve(); calls at the end of each of your log files to return deffered.promise;

关于javascript - AngularJS $q.all() 结果为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21777797/

相关文章:

Javascript 运行总数不断增加

javascript - 将 jQuery 变成 Angular,修复侧边栏不起作用(?)

ruby-on-rails - 使用 AngularJS 访问 API 时,Rails 请求内容类型似乎不正确

javascript - Web 开发的延迟加载和性能

java - 如何使用 HTML5 数据属性获取 session 属性

javascript - 使用 pdf.js 在 Canvas 上绘制矩形并加载 pdf 文件

durandal - 延迟ajax和when() did()的Q解决方案

angularjs - Angular2 和 TSD 出现 "Duplicate identifier"错误

javascript - Q 链接不正确

javascript - 确定 promise 需要多长时间