我正在制作一系列http请求,我需要在返回时将结果存档到列表对象中。我使用有角度的承诺。
因为promises只在for循环结束后解析,所以它们都被归入列表的最后一个索引。
for (var i = 0;i < list.length; i+=1) {
Promise.do(action).then(function(result) {
list[i] //i is always at last index because the for loop has already completed
}
}
答案 0 :(得分:3)
Bind索引作为接收结果的函数的参数:
for (var i = 0;i < list.length; i+=1) {
Promise.do(action).then((function(index, result) {
list[index]
}).bind(null, i));
}
答案 1 :(得分:2)
不要使用标准循环。请改用Array.forEach。每次调用提供给forEach的函数时,你都会得到一个新的闭包,因此我会给你一个新的副本
答案 2 :(得分:1)
我会尝试使用$q.all
:
var promises = [];
for (var i = 0; i < list.length; i += 1) {
promises.push(Promise.do(action));
}
$q.all(promises).then(function(results) {
console.log(results);
});
来自文档:
返回将使用数组/散列解析的单个promise 值,每个值对应于相同索引/键的promise 在promises数组/哈希中。如果任何承诺通过a解决 拒绝,由此产生的承诺将被拒绝 拒绝价值。
答案 3 :(得分:0)
同意Bergi的评论,这看起来像臭名昭着的循环问题。但是,我在注意到Bergi的评论之前输入了我的答案,所以这里有几个解决方案:
for (var i = 0;i < list.length; i+=1) {
var callback = function(result) {
list[arguments.callee.i]...
}
callback.i = i;
Promise.do(action).then(callback);
}
OR:
for (var i = 0;i < list.length; i+=1) {
var callback = function(n) {
return function(result) {
list[n]...
};
}(i);
Promise.do(action).then(callback);
}
答案 4 :(得分:-1)
您可以在Promise.then块中调用下一轮'循环',如下所示:
function do_thing(i) {
// Are we finished? If so, return.
if (i == list.length) return;
Promise.do(action).then(function(result) {
list[i]
// Do the next thing, only once the previous thing completed.
do_thing(i+1)
}
}
// Start at the first thing.
do_thing(0)
问题在于你失去了发生并行异步调用的好处 - 一切都被序列化 - 所以它会慢一些。使用jQuery承诺,您可以将索引附加到promise对象...这是否可以使用angular?
for (var i = 0;i < list.length; i+=1) {
var p = Promise.do(action)
p.index = i
p.then(function(result) {
// this.index is the value of i so do...
list[this.index]
}
}
这是一个小提示,显示jQuery风格:http://jsfiddle.net/sifriday/0v6vr77y/