问题描述
限时送ChatGPT账号..我的代码循环遍历数组中的 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;
};
推荐答案
这是在 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 次,每个声明都覆盖前一个!因此,每次解析器触发时,它实际上都会解析 same deferred
!
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)
};
这篇关于角度异步事件的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
更多推荐
[db:关键词]
发布评论