Il semble que certains problèmes me empêchent de formuler des requêtes HEAD
et de préserver l'intégrité des données d'un tableau.
Étant donné cet extrait:
var imageTemp = Array();
$('*')
.each(function(index){
if($(this).css('background-image') != 'none'){
imageTemp.Push($(this).css('background-image').slice(5, -2));
}
});
Je capture les URL de toutes les images d'arrière-plan sur une page donnée. Maintenant, en essayant de saisir la taille de chaque image via les requêtes HEAD
pour Content-Length
, j'utilise cet extrait:
var imageData = Array();
for(var i = 0; i < imageTemp.length; i++){
ajaxSizeRequest = $.ajax({
type: "HEAD",
async: true,
url: imageTemp[i],
success: function(message){
imageData.Push([imageTemp[i], ajaxSizeRequest.getResponseHeader('Content-Length')]);
}
});
}
Cependant, lorsque je vide imageData
via console.log
, chaque élément (qui devrait être un tableau contenant l'URL et la longueur du contenu) se termine par [undefined, XXXX]
où XXXX
est toujours la taille du dernier Content-Length
demandé.
Je suis perplexe, bien que cela semble être une question de timing/portée. Ai-je une sorte de condition de course qui se passe ici?
Le problème est que les variables uniques i
et ajaxSizeRequest
capturées par la fonction de rappel sont les mêmes pour toutes les instances de la fonction de rappel. Je pense que si vous appelez une fonction et passez la variable d'index à celle-ci et, en même temps, Étendre la variable de demande localement à la fonction utilisez le paramètre de réponse du gestionnaire done, vous devriez vous retrouver avec des variables indépendantes capturées par le rappel. Il devrait ensuite référencer correctement chaque élément du tableau et chaque variable de réponse.
var imageData = Array();
for(var i = 0; i < imageTemp.length; i++){
updateImageData( i );
}
function updateImageData( i )
$.ajax({
type: "HEAD",
async: true,
url: imageTemp[i],
}).done(function(message,text,jqXHR){
imageData.Push([imageTemp[i], jqXHR.getResponseHeader('Content-Length')]);
});
}
ressemble à votre i
n'est pas correctement fermé
de plus, vous ne pouvez pas utiliser ajaxSizeRequest
car elle aussi pointe vers une seule requête (probablement la dernière, car la boucle s'exécutera très rapidement)
enveloppez simplement votre fonction de rappel success
comme suit, en changeant la référence en ajaxSizeRequest
:
success: (function(i){
return function(data,status,xhr){
imageData.Push([imageTemp[i], xhr.getResponseHeader('Content-Length')]);
};
})(i)
Vous pouvez voir que j'aime bien:
success: function(i){
return function(message){
imageData.Push([imageTemp[i], ajaxSizeRequest.getResponseHeader('Content-Length')]);
}
}(i)
Si quelqu'un a encore des problèmes avec cela, et puisque ce message a déjà 5 ans, voici une version plus «moderne» de la réponse: utilisez simplement let
au lieu de var
dans la boucle for
du message d'origine.
Info: Y a-t-il une raison d'utiliser le mot clé "var" dans ES6? et: MDN - Soit la syntaxe
Vous avez une seule variable i
qui est partagée par tous les rappels.
Étant donné que AJAX est asynchrone, tous les rappels sont exécutés une fois la boucle terminée, et ils reçoivent tous la même i
.
Pour résoudre ce problème, vous devez déplacer l'appel AJAX dans une fonction distincte qui prend i
en tant que paramètre.
Ainsi, chaque rappel recevra un paramètre i
distinct.