[英]AngularJS $q.all() results are null
我正在嘗試實現$ q.all來運行一些函數,然后將所有輸出返回到最后附加到.then的函數中。
在承諾看起來他們正在以正確的順序調用並且$ all .then在最后發生,但結果變量返回一個空數組($ 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()。then
對我來說,事情看起來是正確的順序調用,所以我很困惑為什么我在返回值中得到空值。 我是否錯誤地使用了defer.resolve(value)?
我在這里看了一些其他的例子,但是我還沒弄清楚為什么我沒有得到結果。
謝謝你提供的所有幫助。 由於這也是我的第一篇文章,任何有關我應該包括(或不需要包括)的信息的提示也將不勝感激。
謝謝。 尼爾
您的問題是,您沒有從日志功能本身返回您的承諾,以便$q.all
跟隨。 你正在解決這些承諾並將它們歸還給某個地方,但不是在任何正在傾聽的地方。 函數中調用.then
由被稱為$q
和返回值被發送到了承諾的決議回調.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;
}
然后,在你完成這項工作之后,你將獲得一些結果作為參數,這個參數是在一個類似於doSomethingDeferredWith
返回的promise
類的.then
調用中引用的函數:
doSomethingDeferredWith(data).then(function(deferredResult) {
現在,因為該方式$q
作品,調用doSomethingDeferredWith(data)
返回一個承諾, .then
叫上承諾,在排隊,傳遞的功能, 但直到當前的腳本結束循環不執行 。 這意味着.then
被調用,函數排隊,然后doSomethingDeferred
繼續執行,返回,然后它的調用函數繼續執行,直到調用堆棧清除。 只有在那之后, $q
才有機會回來並運行已解決的承諾的所有回調。
在你的代碼中, doSomethingDeferred
,各種log***
函數,實際上並沒有返回一個promise。 他們返回undefined
。 如果您改為返回我們創建的promise,並且當$q
運行回調而不是doSomethingDeferred
結束時將解析,您將在$q.all
的回調中獲取數據。
要修復代碼,請更改deffered.resolve();
在每個日志文件的末尾調用以return deffered.promise;
然后,日志函數的返回值將不會被undefined
,它們將是$q
可以遵循的承諾,並且在完成所有三個調用之后立即對所有三個.resolve
調用運行回調,設置$scope.runFrom2
值為['One','Two','Three']
數組,因為每個單獨的promise都使用deferring函數的閉包框架中的value
解析。
tl;博士版
更改
deffered.resolve();
在每個日志文件的末尾調用以return deffered.promise;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.