我在angularjs中有这个代码,它为循环的每个索引向API发送一个http请求,问题是我想访问promise中的索引,但是这给了我错误的索引。
avgCEN=CENa/CENc;
avgECE=ECEa/ECEc;
avgBINF=BINFa/BINFc;
CONSOLE:
指数外承诺:0
指数外承诺:1
承诺内的索引:2
承诺内的索引:2
我想要这个:
指数外承诺:0
承诺内的索引:0
指数外承诺:1
承诺里面的索引:1答案 0 :(得分:1)
使用let statement代替var statement来声明索引:
//for (var index = 0; index < array.length; index++) {
for (let index = 0; index < array.length; index++) {
console.log("index outside promise: "+index);
var elements = array[index];
MyResource.save(elements).$promise.then(function(response){
console.log("index inside promise: "+index);
//In this part show me the error, because the index is wrong
array[index].status = true;
}, function failed(response){
console.log(response);
});
}
或者使用IIFE:
for (var index = 0; index < array.length; index++) {
//IIFE
(function (index) {
console.log("index outside promise: "+index);
var elements = array[index];
MyResource.save(elements).$promise.then(function(response){
console.log("index inside promise: "+index);
//In this part show me the error, because the index is wrong
array[index].status = true;
}, function failed(response){
console.log(response);
});
}(index));
}
因为index
变量被声明为var
,JavaScript编译器会创建一个closure,它共享对index
变量的引用。引用包含的值在调用.then
方法内的函数之前发生更改。
要在调用.then
方法内的函数之前保留该值,请将其声明为带有let statement的块范围变量,或使用Immediately Invoked Function Expression (IIFE) idiom。
答案 1 :(得分:0)
您可以尝试将API调用逻辑拆分为单独的函数:
function originalFunction() {
for (var index = 0; index < array.length; index++) {
var elements = array[index];
save(elements, index);
}
}
function save(elements, index) {
MyResource.save(elements).$promise.then(function(response){
doSomething(index);
}, function failed(response){
console.log(response);
});
}
上面的解决方案将使您可以在API成功处理程序中访问正确的索引。但是,您无法按指定方式打印字符串,因为API调用是异步操作,而for循环中的其他代码同步运行。这意味着当您在promise语句的“外部”打印时,在API调用完成之后才能打印相应的消息。但是,下一个“外部”语句不会等到上一次API调用完成后再进行下一次API调用。这就是为什么print语句不符合您指定的顺序。
如果你绝对必须按照你的描述打印出语句,那么你需要阻止后续的API调用发生,直到当前的API完成,这将使整个过程变慢。如果这是您想要做的,以下代码应该起作用:
function originalFunction(nextInd) {
// default the id of the next call to 0
nextInd = nextId || 0;
// If the index is valid for the current array, call the API method
if (nextInd >= 0 && nextInd < array.length) {
console.log("index outside promise: "+nextInd );
var elements = array[nextInd];
save(elements, nextId);
}
}
function save(elements, index) {
MyResource.save(elements).$promise.then(function(response){
console.log("index inside promise: "+index);
doSomething(index);
// kick off the API call for the next element in the array
originalFunction(index++);
}, function failed(response){
console.log(response);
// kick off the API call for the next element in the array
originalFunction(index++);
});
}
// You can still call the originalFunction without parameters to kick it off
originalFunction();