异步Javascript变量覆盖

Asynchronous Javascript Variable Overwrite

代码有一个问题,即在调用异步函数时变量会被写入。 怎么修好?

码:

1
2
3
4
5
6
7
for (x in files) {

 asynchronousFunction(var1, var2, function(){
      console.log(x.someVaraible);
  });

}

现在的问题是,当调用asynchronousFunction中的回调函数时,x.files变量已更新为json数组文件中的下一个变量。 我希望变量应该包含以前的值。

回调函数中的变量数不能更改,因此无法在回调函数中发送变量名。


在javascript中使用'local'变量的问题是你的变量实际上有函数作用域,而不是块作用域 - 比如java和c#等

解决这个问题的一种方法是使用具有块范围的let,但目前只有firefox支持此功能。

所以这段代码只适用于firefox:

1
2
3
4
5
6
7
for (var x in files) {
  // This variable has BLOCK scope
  let file = files[x];
  asynchronousFunction(var1, var2, function(){
     console.log(file.someVaraible);
  });
}

对于其他浏览器,替代方法是使用闭包

1
2
3
4
5
6
7
8
for (var x in files) {
  var file = files[x];
  asynchronousFunction(var1, var2, (function(file){
      return function() {
                console.log(file.someVaraible);
             };
  })(file);
}

另一种方法是使用map / forEach,假设文件的数据类型是一个数组。

1
2
3
4
5
files.forEach(function(file) {
     asynchronousFunction(var1, var2, function(){
                console.log(file.someVaraible);
             });
});

如果它不是数组,那么你总是可以使用这种技术

1
2
3
4
5
 [].forEach.call(files, function(file) {
     asynchronousFunction(var1, var2, function(){
                console.log(file.someVaraible);
             });
});

当然,更全面的写作方式

1
2
Array.prototype.forEach.call(files, function(file) {
     // As before

但我觉得[].forEach对眼睛更好


您需要从回调函数创建的闭包中解开x。简短回答:

1
2
3
4
5
6
7
8
9
for (x in files) {
    asynchronousFunction(var1, var2,
        (function(y){
            return function(){
                console.log(y.someVaraible);
            }
        })(x)
    );
}

有关更长的答案和解释,请参阅我对上一个问题的回答:请解释在循环中使用JavaScript闭包


X被迭代,所以在调用回调函数时,x将是循环中的最后一个迭代函数。

通过像这样使x本地修复:

1
2
3
4
5
6
7
8
for (x in files) {
    (function() {
        var x = arguments[0];
        asynchronousFunction(var1, var2, function() {
            console.log(x.someVaraible);
        });
    }(x));
}


您需要将变量绑定到函数定义,或将变量传递给函数。我可能会采取一种组合方法,例如:

1
2
3
4
5
6
7
for (x in files) {
    var local_x = x;
    var fn = function () {
         theRealFunction( local_x );
    };
    asynchronousFunction(var1, var2, fn);
}

虽然在你的例子中我不需要将theRealFunction()称为如此少量的代码(只是console.log)。