6

コードには、非同期関数が呼び出されたときに変数が上書きされるという問題があります。どうすれば修正できますか?

コード:

for (x in files) {

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

}

ここで問題となるのは、非同期関数のコールバック関数が呼び出されると、x.files変数がjson配列ファイル内の次の変数に更新されていることです。変数に前の値が含まれている必要があります。

コールバック関数の変数の数は変更できないため、コールバック関数で変数名を送信することはできません。

4

4 に答える 4

13

javascriptで「ローカル」変数を使用する場合の問題は、JavaやC#などのように、変数がブロックスコープではなく実際に関数スコープを持っていることです。

これを回避する1つの方法はlet、ブロックスコープを持つを使用することですが、現在、Firefoxのみがこれをサポートしています。

したがって、このコードはFirefoxでのみ機能します。

for (var x in files) {
  // This variable has BLOCK scope
  let file = files[x];
  asynchronousFunction(var1, var2, function(){
     console.log(file.someVariable);
  }); 
}

他のブラウザの場合、代替手段はクロージャを使用することです

for (var x in files) {
  var file = files[x];
  asynchronousFunction(var1, var2, (function(file){
      return function() {
                console.log(file.someVariable);
             };
  })(file); 
}

これを行う別の方法は、ファイルのデータ型が配列であると想定して、map/forEachを使用することです。

files.forEach(function(file) {
     asynchronousFunction(var1, var2, function(){
                console.log(file.someVariable);
             });
});

配列でない場合は、いつでもこの手法を使用できます

 [].forEach.call(files, function(file) {
     asynchronousFunction(var1, var2, function(){
                console.log(file.someVariable);
             });
});

これを書くためのより完全な方法はもちろんです

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

しかし、私[].forEachは目にはより良いと感じています。

于 2012-07-31T19:13:37.457 に答える
1

xコールバック関数によって作成されたクロージャーからを解きほぐす必要があります。短い答え:

for (x in files) {
    asynchronousFunction(var1, var2,
        (function(y){
            return function(){
                console.log(y.someVaraible);
            }
        })(x)
    ); 
}

より長い答えと説明については、前の質問に対する私の答えを参照してください:ループでのJavaScriptクロージャの使用について説明してください

于 2012-07-31T19:11:00.840 に答える
0

変数を関数定義にバインドするか、変数を関数に渡す必要があります。私はおそらく、次のような組み合わせアプローチを採用します。

for (x in files) {
    var local_x = x;
    var fn = function () {
         theRealFunction( local_x );
    };
    asynchronousFunction(var1, var2, fn);
}

あなたの例では、そのような少量のコード(console.logだけ)としてtheRealFunction()を呼び出す必要はありませんが。

于 2012-07-31T19:07:12.913 に答える
0

Xは反復されるため、コールバック関数が呼び出されるまでに、xはループからの最後の反復関数になります。

x次のようにローカルにすることで修正します。

for (x in files) {
    (function() {
        var x = arguments[0];
        asynchronousFunction(var1, var2, function() {
            console.log(x.someVaraible);
        });
    }(x));
}
于 2012-07-31T19:08:18.160 に答える