Javascript 数组的异步更新
我有一个视图,可以在其中渲染推文。在tweets中,有一个用户_提及数组。从这个数组中,我想获得一个用户,向API发出另一个请求,获得用户的化身,然后渲染它。 视图看起来像:Javascript 数组的异步更新,javascript,angularjs,asynchronous,Javascript,Angularjs,Asynchronous,我有一个视图,可以在其中渲染推文。在tweets中,有一个用户_提及数组。从这个数组中,我想获得一个用户,向API发出另一个请求,获得用户的化身,然后渲染它。 视图看起来像: <md-item ng-repeat="item in content"> <div class="md-tile-left" ng-if="item.show"> <img ng-src="{{item.thumb}}" class="face" alt="{{item.nam
<md-item ng-repeat="item in content">
<div class="md-tile-left" ng-if="item.show">
<img ng-src="{{item.thumb}}" class="face" alt="{{item.name}}">
</div>
<div class="md-tile-content">
{{item.text}}
</div>
</md-item>
for(var i = 0; i < data.length; i++) {
if(data[i].user_mentions[0]) {
UserAvatar.get(data[i].user_mentions[0].screen_name).then(function(data){
$scope.content[i].thumb = data.avatar;
$scope.content[i].show = true;
});
}
}
我意识到这只是一个让它工作的技巧,但是有没有更聪明的方法呢?问题是,您试图在for循环中使用闭包,但它并不像您发现的那样工作。你的黑客是修复它的一个选择。另一种方法是使用
forEach()
/map()
或iLife((函数(i){…})(i);
)将循环包装到函数中
在您的示例中,我将执行以下操作:
var promises = data.map(function(item, index) {
if (item.user_mentions[0]) {
return UserAvatar.get(item.user_mentions[0].screen_name)
.then(function(itemData) {
$scope.content[index].thumb = itemData.avatar;
$scope.content[index].show = true;
});
} else {
return $q();
}
});
$q.all(promises).then(function() {
// All complete
});
我意识到,这只是一个黑客使其工作,但有一个
更聪明的方法
正如@MukeshAgarwal在评论中所说,这并不是真正的黑客行为,因为UserAvatar.get
是一个异步过程
因此,您必须在异步调用时捕获i
的值
您使用的方法没有那么糟糕,但另一种方法是使用立即调用的函数:
此不起作用:
for (var i = 0; i < 10; i++) {
// do something async
setTimeout(function() {
console.log(i); // <- This will log 10 each time (the value of i at execution)
}, 1000)
}
for(变量i=0;i<10;i++){
//做一些异步的事情
setTimeout(函数(){
console.log(i);//每当调用函数时,您必须记住,当它被执行时,作用域中的所有变量(不仅是$scope
,还有像i这样的外部变量)由外部函数创建的内容将对函数可见,我想您已经意识到了这一点,需要意识到的一点是,在的处理程序中实际上不需要I
。然后
您需要获取索引I
中的内容,但如何摆脱这种依赖关系?我提供了两种可能的解决方案:
(一)
在这个解决方案中,IIFE返回一个函数,该函数将作为处理程序,但IIFE实际上将捕获所分析内容的值,因此当返回的内部函数(即的oncompleted
处理程序)被调用时,就没有i
依赖关系
奖励:以下规则对我处理函数有很大帮助:
var promises = data.map(function(item, index) {
if (item.user_mentions[0]) {
return UserAvatar.get(item.user_mentions[0].screen_name)
.then(function(itemData) {
$scope.content[index].thumb = itemData.avatar;
$scope.content[index].show = true;
});
} else {
return $q();
}
});
$q.all(promises).then(function() {
// All complete
});
函数将在其定义的位置执行
我不记得我在哪里读过它,我想它是在Nicholas Zakas'中,强烈推荐的:)这不是一个黑客行为,因为获取化身是异步过程,所以I值将得到增量。如果对你来说变得困难,你也可以使用异步库you@MukeshAgarwal:谢谢!所以你认为这是可以用于公关的东西生产环境?@Mauricioppe:谢谢!我非常喜欢你提供的第二个解决方案。
for (var i = 0; i < 10; i++) {
(function() {
var j = i; // <- The value of i is captured in j. j is in a closure
// do something async
setTimeout(function() {
console.log(j); // <- This will log 0, then 1, then 2 ... then 9
}, 1000)
})()
}
function getAvatar(name, contentToUpdate) {
return UserAvatar.get(name)
.then(function (data) {
contentToUpdate.thumb = data.avatar;
contentToUpdate.show = true;
});
}
for(var i = 0; i < data.length; i++) {
if(data[i].user_mentions[0]) {
getAvatar(data[i].user_mentions[0].screen_name, $scope.content[i]);
}
}
for(var i = 0; i < data.length; i++) {
if(data[i].user_mentions[0]) {
UserAvatar.get(data[i].user_mentions[0].screen_name).then((function(content) {
return function (data) {
content.thumb = data.avatar;
content.show = true;
}
})($scope.content[i]));
}
}