2012-11-15 6 views
3

J'ai récemment posé une question sur le comportement de jquery différée dans une boucle for. Link herejQuery comportement différé dans la boucle for

J'ai reçu une réponse de travail, mais je ne comprends pas pourquoi cela fonctionne.

Si je le code suivant:

function update(callbacks) { 
    return $.Deferred(function(dfr) { 
     setTimeout(function() { 
      callbacks.success() 
     }, 1000); 
     dfr.resolve(); 
    }).promise(); 
} 

function updateElements(deferreds) { 
    for (var i = 0; i < 5; i++) { 
     (function() { 
      var index = i; 
      deferreds.push(update({ 
       success: function() { 
        alert(index); 
       } 
      })); 
     })(); 
    } 
}; 

(function() { 
    var deffereds = []; 
    updateElements(deffereds); 
    $.when.apply($, deffereds).then(function() {}, function() {}); 
})();​ 

Il retourne 5 fenêtres d'alerte avec les valeurs 0 jusqu'à 4. Si je change la méthode updateElements à:

function updateElements(deferreds) { 
    for (var i = 0; i < 5; i++) { 
     var index = i; 
     deferreds.push(update({ 
      success: function() { 
       alert(index); 
      } 
     })); 
    } 
}; 

Il retourne 5 alerte les fenêtres avec la valeur 4 seulement. Quelqu'un pourrait-il expliquer ce comportement? J'ai du mal à comprendre d'où vient la différence.

Merci!

+2

La boucle passe en quelques millisecondes, la mise à jour du nombre, et depuis différé est asynchrone et attend, au moment où il indique le nombre, la variable a changé et la boucle est terminée depuis longtemps. En l'enveloppant dans une fonction anonyme, la valeur de la variable 'index' est conservée et n'est pas mise à jour, car il s'agit d'une variable locale définie à chaque itération. – adeneo

+0

duplication possible de [fermeture Javascript à l'intérieur des boucles - exemple pratique simple] (http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) –

Répondre

3

La raison pour laquelle il fait cela est parce que vous avez fermé sur une boucle avec

(function() { 
     var index = i; 
     deferreds.push(update({ 
      success: function() { 
       alert(index); 
      } 
     })); 
})(); 

Cette auto exécution bloc se transforme en une valeur statique, car il n'a pas de valeurs externes transmises. Comme dans la réponse que vous avez lié , vous devez transmettre cette valeur. Notez la différence de clé où la valeur est donnée à la fin de l'IEFE (expression de la fonction exécutée immédiatement). Désolé pour les casquettes, mais cela doit être souligné.

(function(VALUE_ACCEPTED){ 
    //VALUE_ACCEPTED accepts the passed value of VALUE_PASSED 
})(VALUE_PASSED) 

Pour que votre code devient ceci:

function updateElements(deferreds) { 
for (var i = 0; i < 5; i++) { 
    (function(valueAccepted) { // valueAccepted = the passed in value from i 
     var index = valueAccepted; 
     deferreds.push(update({ 
      success: function() { 
       alert(index); 
      } 
     })); 
    })(i); // pass in i to valueAccepted 
} 
};