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
).
3 réponses
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).
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');
}
});
}
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)
});
}
Questions connexes
De nouvelles questions
javascript
Pour des questions concernant la programmation dans ECMAScript (JavaScript / JS) et ses divers dialectes / implémentations (hors ActionScript). Veuillez inclure toutes les balises pertinentes dans votre question; par exemple, [node.js], [jquery], [json], etc.