问题描述
我的代码循环遍历数组中的10个项目,对每个项目发出请求,然后将返回的数据推送到数组。一切运行正常,直到 $ q.all
行。
The code I have loops through 10 items in an array, makes a request for each item, then pushes the returned data to an array. Everything runs fine until the $q.all
line.
details.getDetails = function(idSet, pageNum) {
var page = idSet[pageNum],
mainDeferred = $q.defer(),
promises = [],
combinedItems = [];
for(var i=0; i<page.length; i++){
var deferred = $q.defer();
ngGPlacesAPI.placeDetails({placeId: page[i][i]})
.then(function(data){
combinedItems.push(data);
console.log(combinedItems); /// This shows the objects being pushed into the array
deferred.resolve();
});
promises.push(deferred.promise);
}
console.log(promises); /// This shows the 10 promises
$q.all(promises).then(function() { /// Nothing after this line runs
console.log('test', mainDeferred.promise); /// This logs nothing
mainDeferred.resolve(combinedItems);
});
return mainDeferred.promise;
};
推荐答案
在处理async时,这是一个非常常见的错误javascript。
This is a pretty common error when dealing with async in javascript.
问题应该是:当解析器(你传递给 .then
的函数)查找变量 deferred
,它返回什么变量?。然后回答是,他们都引用你声明的最后一个 deferred
。
The question should should ask is: "when the resolver (the function you pass to .then
) looks up the variable deferred
, what variable does it get back?". Then answer is, they all reference the very last deferred
you declare.
问题是,你是在宣布解析函数之外的 deferred
。记住javascript如何查找变量:
The problem is, you're declaring deferred
outside of your resolve function. Remember how javascript looks up variables:
- 是变量(在我们的例子中,
deferred
)在即时功能范围内可用? (在我们的例子中,没有) - 遍历父范围,直到找到具有给定名称的变量。
- Is the variable (in our case,
deferred
) available in the immediate function scope? (in our case, no) - Traverse up parent scopes until we find a variable with the given name.
当解析器触发时,你已经重新声明 deferred
10次,每个声明都会覆盖前一个声明!因此每次解析器触发时,它实际上都会解析相同的 延迟
!
By the time the resolver fires, you've redeclared deferred
10 times, each declaration overwriting the previous one! So each time a resolver fires, it actually resolves the same deferred
!
答案是在一个闭包中包装你的 deferred
声明:
The answer is to wrap your deferred
declaration in a closure:
for(var i=0; i<page.length; i++){
(function(){
var deferred = $q.defer();
ngGPlacesAPI.placeDetails({placeId: page[i][i]})
.then(function(data){
combinedItems.push(data);
console.log(combinedItems); /// This shows the objects being pushed into the array
deferred.resolve();
});
promises.push(deferred.promise);
})()
}
但实际上,您可以简化整个计划并避免延期。如果这对您有意义,请告诉我!:
But really, you can simplify your whole program and avoid the deferreds. Let me know if this makes sense to you!:
details.getDetails = function(idSet, pageNum) {
var page = idSet[pageNum];
// generate an array from 0 to page.length
var items = Array.apply(null, { length: page.length })
var promises = items.map(function (i) {
return ngGPlacesAPI.placeDetails({placeId: page[i][i]});
})
return $q.all(promises)
};
这篇关于角度异步事件的麻烦的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!