AngularJS $q.all() 结果为空



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

目前,承诺看起来像是以正确的顺序调用的,并且 .then $all发生在最后,但结果变量返回一个空值数组($q.all 中的每个承诺一个

)JS小提琴可以在 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和logIII不会是相同的函数。

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)?

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

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

谢谢。 尼尔

您的问题是您没有从日志函数本身返回您的承诺以供$q.all遵循。 你正在解决承诺并将它们归还到某个地方,而不是任何正在倾听的地方。$q调用.then中的函数,返回值被发送到承诺.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;
}

然后,在完成此操作后,您将获得一些结果作为调用中引用的函数的参数,以.thenpromise类似于从doSomethingDeferredWith返回的函数:

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

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

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

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

tl;博士版本

将每个日志文件末尾的deffered.resolve();调用更改为return deffered.promise;

相关内容

  • 没有找到相关文章

最新更新