Asynchrone variable Javascript écraser

Le code a un problème pour lequel la variable est écrite lorsque la fonction asynchrone est appelée. Comment peut-on le réparer?

Code:

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

Maintenant, le problème est que lorsque la fonction de rappel en fonction de la fonction asynchrone est appelée la variable x.files a été mise à jour pour la prochaine variable dans les fichiers du tableau json. Je veux que la variable contienne la valeur précédente.

Le nombre de variables dans la fonction de rappel ne peut pas être modifié, donc le nom de la variable ne peut pas être envoyé dans la fonction de rappel.

Le problème avec l'utilisation de variables «locales» dans javascript est que vos variables ont effectivement la portée de la fonction, plutôt que la portée du bloc – comme java et c # etc a

Une façon de contourner cela est d'utiliser let qui a une portée de bloc, mais seuls firefox prend en charge ceci actuellement.

Donc, ce code fonctionnerait uniquement dans Firefox:

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

Pour les autres navigateurs, l'alternative consiste à utiliser des fermetures

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

Une autre façon que vous pouvez faire est d'utiliser map / forEach, en supposant que le type de données des fichiers est un tableau.

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

Si ce n'est pas un tableau, vous pouvez toujours utiliser cette technique

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

La manière plus complète d'écrire ceci est évidemment

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

Mais je me sens [].forEach est plus agréable pour les yeux

Vous devez désinstaller le x de la fermeture créée par la fonction de rappel. Réponse courte:

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

Pour une réponse plus longue et une explication, reportez-vous à ma réponse à une question précédente: expliquez l'utilisation des fermetures de JavaScript dans les boucles

Vous devez soit lier la variable à la définition de fonction, soit passer la variable dans la fonction. Je prendrais probablement une approche combinée, quelque chose comme:

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

Bien que dans votre exemple, je n'aurais pas besoin d'appeler theRealFunction () comme étant une petite quantité de code (juste console.log).

X se fait itérer de sorte que lorsque la fonction de rappel est appelée, x sera la dernière fonction itérée de la boucle.

Correction en faisant de x local comme ceci:

 for (x in files) { (function() { var x = arguments[0]; asynchronousFunction(var1, var2, function() { console.log(x.someVaraible); }); }(x)); }