2011-01-17 5 views
13

У меня, похоже, возникли проблемы с получением запросов HEAD и сохранением целостности данных в массиве.Запрос Ajax HEAD через Javascript/jQuery

Учитывая этот фрагмент:

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')]); 
     } 
    }); 
} 

Однако, когда я свалка imageData через console.log, я каждый элемент (который должен быть массив, содержащий URL и содержание длина) заканчивается как [undefined, XXXX] где XXXX всегда размер последнего просила Content-Length

Я в тупике, хотя это, кажется, временная/обзорная проблема. Есть ли у меня какое-то состояние гонки?

+4

Вместо 'переменной ajaxSizeRequest', вы можете использовать второй параметр в' success' CALLBACK в. – SLaks

ответ

17

Проблема состоит в том, что отдельные переменные 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')]); 
    }); 
} 
+0

Спасибо alot ** tvanfosson **; Это работает как шарм. Я сделал анонимный 'updateImageData', чтобы избежать загрязнения моего сценария. – Dan

+0

избегать использования 'success', предотвращать беспорядок кода !, использовать' .done (function (text, status, xhr) {......}; 'вместо этого. –

+0

@EladKarako - довольно старый ответ, я обновил чтобы отразить текущую передовую практику. – tvanfosson

0

У вас есть одна переменная i, которая разделяется всеми обратными вызовами.
Поскольку AJAX является асинхронным, все обратные вызовы запускаются после завершения цикла, и все они получают то же самое i.

Чтобы исправить это, вам необходимо переместить вызов AJAX в отдельную функцию, которая принимает параметр i.
Таким образом, каждый обратный вызов получит отдельный параметр i.

2

выглядит ваш i ISNT правильно закрыта в

кроме того, вы не можете использовать ajaxSizeRequest, потому что это тоже указывает на только один запрос (возможно, последний, потому что цикл будет выполняться очень быстро)

просто обернуть success функцию обратного вызова следующим образом, изменяя ссылку на ajaxSizeRequest:

success: (function(i){ 
    return function(data,status,xhr){ 
    imageData.push([imageTemp[i], xhr.getResponseHeader('Content-Length')]); 
    }; 
})(i) 
1

Вы можете сфера мне нравится так:

success: function(i){ 
    return function(message){ 
     imageData.push([imageTemp[i], ajaxSizeRequest.getResponseHeader('Content-Length')]); 
    } 
}(i) 
0

Если кто-то все еще возникают проблемы с этим, и так как этот пост, как, 5 лет старый уже, вот более «современный» вариант ответа: просто использовать let вместо var в оригинале Поста for петля.

Информация: Is there any reason to use the “var” keyword in ES6? и: MDN - Let syntax

Смежные вопросы