J'utilise la requête AJAX suivante pour récupérer un certain nombre de pages, dont j'ai les titres dans un tableau appelé pages. Chaque réponse va dans une div séparée, et je veux donner à chacune de ces divs un identifiant identique au titre de la page.

Bien sûr, au moment où mes demandes reviennent, [i] a atteint pages.length et tous mes noms de div sont undefined.

for ( i = 0; i < pages.length; i++ ) {
  $.ajax({
    //async:false makes it work but it slows things down too much
    url: 'ajax_' + pages[i],
    success: function(data) {
      $('<div id="' + pages[i] + '">' + data + '</div>').appendTo('div.content');
      }
  });
 }

Comment puis-je obtenir un bon verrouillage entre les variables de demande et de réponse?

Merci!

NB Je préfère le garder asynchrone (c'est-à-dire ne pas utiliser async:false).

0
djb 23 nov. 2011 à 20:23

3 réponses

Meilleure réponse

Rapide et sale:

$.ajax({
    url: 'ajax_' + pages[i],

    context: i, // set `this` to `i` in the callback

    success: function(data) {
        // `this` is the correct, "frozen" `i`
        $('<div id="' + pages[this] + '">' + data + '</div>').appendTo('div.content');
    }
});

Notez que this est toujours contraint dans un objet comme new Number(2) au lieu de 2. Néanmoins, ils peuvent être utilisés pour accéder aux indices de tableau.

Il existe des moyens plus propres de le faire, comme créer une fermeture, mais cela peut bien fonctionner pour vous (c'est-à-dire si vous n'utilisez pas this pour autre chose dans le rappel).

1
pimvdb 23 nov. 2011 à 16:43

Vous devez toujours utiliser le mot clé var dans vos variables de boucle for pour les étendre correctement. Sinon, cette boucle accède à une variable globale appelée i, qui peut ou non entrer en conflit avec une autre boucle.

Mais ce n'est pas la solution au problème exact que vous avez. Vous devez mettre en cache une référence à la page actuelle et l'utiliser dans la réponse ajax.

for ( var i = 0; i < pages.length; i++ ) {
  var page = pages[i];
  $.ajax({
    //async:false makes it work but it slows things down too much
    url: 'ajax_' + page,
    success: function(data) {
      $('<div id="' + page + '">' + data + '</div>').appendTo('div.content');
      }
  });
 }
0
Mike Ruhlin 23 nov. 2011 à 16:27

JavaScript a quelque chose appelé portée lexicale, qui est différente de la portée des blocs que la plupart connaissent. En JS, pour donner à quelque chose une nouvelle portée, il doit être à l'intérieur d'une autre fonction, pas seulement des accolades {}.

La raison pour laquelle async: false fonctionne parce que vous le forcez à attendre la réponse avant de continuer, ce qui évite votre problème de portée.

Essaye ça:

for ( i = 0; i < pages.length; i++ ) {
    $.ajax({
        //async:false makes it work but it slows things down too much
        url: 'ajax_' + pages[i],
        success: (function(index){ 
              return function(data) {
                  $('<div id="' + pages[i] + '">' + data + '</div>').appendTo('div.content');
              };
        })(i)
    });
}
0
Matt 23 nov. 2011 à 16:43
8245608