Запрос Ajax HEAD через Javascript/jQuery
Кажется, у меня возникают проблемы с созданием запросов HEAD
и сохранением целостности данных в массиве.
Учитывая этот фрагмент:
var imageTemp = Array();
$('*')
.each(function(index){
if($(this).css('background-image') != 'none'){
imageTemp.push($(this).css('background-image').slice(5, -2));
}
});
Я фиксирую URL всех фоновых изображений на данной странице. Теперь, пытаясь захватить размер каждого изображения с помощью HEAD
запросов для Content-Length
, я использую этот фрагмент:
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')]);
}
});
}
Однако, когда я dump imageData
через console.log
, каждый элемент (который должен быть массивом, содержащим URL-адрес и длину содержимого) заканчивается как [undefined, XXXX]
, где XXXX
всегда равен размеру последний запрос Content-Length
Я в тупике, хотя, похоже, проблема с хронометражем/неопределенностью. Есть ли у меня какое-то состояние гонки?
Ответы
Ответ 1
Проблема заключается в том, что одиночные переменные i
и ajaxSizeRequest
, захваченные функцией обратного вызова, являются одинаковыми переменными для всех экземпляров функции обратного вызова. Я думаю, что если вы вызываете функцию и передаете ей индексную переменную и, в то же время, область , локальная переменная запроса для самой функции использует параметр ответа обработчика, вы должны в конечном итоге с независимыми переменными, захваченными обратным вызовом. Затем он должен правильно ссылаться на каждый элемент массива и каждую переменную ответа.
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')]);
});
}
Ответ 2
выглядит как ваш i
не правильно закрыт
Кроме того, вы не можете использовать ajaxSizeRequest
, потому что он тоже указывает только на один запрос (возможно, последний, потому что цикл будет выполняться очень быстро)
просто оберните функцию обратного вызова success
следующим образом, изменив ссылку на ajaxSizeRequest
:
success: (function(i){
return function(data,status,xhr){
imageData.push([imageTemp[i], xhr.getResponseHeader('Content-Length')]);
};
})(i)
Ответ 3
Вы можете изменить область видимости так:
success: function(i){
return function(message){
imageData.push([imageTemp[i], ajaxSizeRequest.getResponseHeader('Content-Length')]);
}
}(i)
Ответ 4
У вас есть одна переменная i
, которая разделяется всеми обратными вызовами.
Поскольку AJAX является асинхронным, все обратные вызовы запускаются после завершения цикла, и все они получают одинаковый i
.
Чтобы исправить это, вам нужно переместить вызов AJAX в отдельную функцию, которая принимает i
как параметр.
Таким образом, каждый обратный вызов получит отдельный параметр i
.
Ответ 5
Если у кого-то все еще есть проблемы с этим, и поскольку этот пост, например, уже 5 лет, вот более "современная" версия ответа: просто используйте let
вместо var
в исходном сообщении for
.
Информация: Есть ли причина использовать ключевое слово "var" в ES6?
и: MDN - Пусть синтаксис