angular 中的异步事件有问题
Trouble with asynchronous events in angular
我的代码循环遍历数组中的 10 个项目,对每个项目发出请求,然后将返回的数据推送到一个数组。一切运行正常,直到 $q.all
行。
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 中处理异步时,这是一个非常常见的错误。
应该问的问题是:"when the resolver (the function you pass to .then
) looks up the variable deferred
, what variable does it get back?"。那么答案是,它们都引用了您声明的最后一个 deferred
。
问题是,您在解析函数之外声明 deferred
。记住 javascript 如何查找变量:
- 变量(在我们的例子中,
deferred
)在直接函数范围内可用吗? (在我们的例子中,没有)
- 向上遍历父作用域,直到找到具有给定名称的变量。
解析器启动时,您已重新声明 deferred
10 次,每次声明都会覆盖前一次声明!所以每次解析器触发时,它实际上解析了 same deferred
!
答案是将您的 deferred
声明包装在闭包中:
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);
})()
}
但实际上,您可以简化整个程序并避免延迟。如果这对你有意义,请告诉我!:
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)
};
我的代码循环遍历数组中的 10 个项目,对每个项目发出请求,然后将返回的数据推送到一个数组。一切运行正常,直到 $q.all
行。
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 中处理异步时,这是一个非常常见的错误。
应该问的问题是:"when the resolver (the function you pass to .then
) looks up the variable deferred
, what variable does it get back?"。那么答案是,它们都引用了您声明的最后一个 deferred
。
问题是,您在解析函数之外声明 deferred
。记住 javascript 如何查找变量:
- 变量(在我们的例子中,
deferred
)在直接函数范围内可用吗? (在我们的例子中,没有) - 向上遍历父作用域,直到找到具有给定名称的变量。
解析器启动时,您已重新声明 deferred
10 次,每次声明都会覆盖前一次声明!所以每次解析器触发时,它实际上解析了 same deferred
!
答案是将您的 deferred
声明包装在闭包中:
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);
})()
}
但实际上,您可以简化整个程序并避免延迟。如果这对你有意义,请告诉我!:
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)
};