web-dev-qa-db-fra.com

Lors de l'utilisation de rappels dans une boucle en javascript, existe-t-il un moyen d'enregistrer une variable mise à jour dans la boucle pour une utilisation dans le rappel?

Disons que j'ai quelque chose comme suit:

for(var i = 0; i < length; i++){
  var variable = variables[i];
  otherVariable.doSomething(variable, function(err){ //callback for when doSomething ends
    do something else with variable;
  }

Au moment où les rappels sont appelés, variable sera inévitablement la dernière variable pour tous les rappels, au lieu d'être différente pour chaque rappel, comme je le voudrais. Je me rends compte que je pourrais passer variable à doSomething() puis le récupérer dans le cadre du rappel, mais doSomething() fait partie d'une bibliothèque externe, et je ' Je préfère ne pas jouer avec le code source pour cela.

Ceux d'entre vous qui connaissent JavaScript mieux que moi savent-ils s'il existe d'autres façons de faire ce que j'aimerais faire?

Bien, et merci,
Sami

67
thisissami

Une façon courante, mais laide, de gérer cette situation consiste à utiliser une autre fonction qui est immédiatement invoquée pour créer une portée pour contenir la variable.

for(var i = 0; i < length; i++) {
  var variable = variables[i];
  otherVariable.doSomething(function(v) { return function(err) { /* something with v */ }; }(variable));
}

Notez que dans la fonction immédiatement invoquée, le rappel en cours de création et renvoyé fait référence au paramètre à la fonction v et non à l'extérieur variable. Pour améliorer la lecture, je suggère d'extraire le constructeur du rappel en tant que fonction nommée.

function callbackFor(v) {
  return function(err) { /* something with v */ };
}
for(var i = 0; i < length; i++) {
  var variable = variables[i];
  otherVariable.doSomething(callbackFor(variable));
}
52
aparker42

Ok, j'ai semblé comprendre ça. Ce que je devais faire était de mettre un wrapper function(var) autour de otherVariable.doSomething(), donc le code mis à jour se présente comme suit:

for(var i = 0; i < length; i++){
  var variable = variables[i];
  (function(var){ //start wrapper code
    otherVariable.doSomething(var, function(err){ //callback for when doSomething ends
      do something else with var; //please note that i'm dealing with var here, not variable
    }
  })(variable);//passing in variable to var here
}

j'espère que cela aidera quelqu'un d'autre qui se retrouvera coincé dans quelque chose comme ça à l'avenir!

@ aparker42, je serais toujours ravi d'entendre votre réponse à ma question dans le commentaire de votre question, car cela m'embrouille toujours.

EDIT: bien sûr, puisque c'est du javascript, vous ne voudriez pas utiliser var comme nom de variable.

38
thisissami