AJAX HEAD запрос через Javascript / JQuery - PullRequest
14 голосов
/ 17 января 2011

У меня, кажется, есть некоторые проблемы с выполнением 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')]);
        }
    });
}

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

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

Ответы [ 5 ]

20 голосов
/ 17 января 2011

Проблема в том, что отдельные переменные i и ajaxSizeRequest, захваченные функцией обратного вызова, являются одинаковыми переменными для всех экземпляров функции обратного вызова. Я думаю, что если вы вызовете функцию и передадите ей переменную индекса и в то же время поместите переменную запроса локально в саму функцию используйте параметр ответа обработчика done, вы должны получить независимые переменные, захваченные обратным вызовом. Затем он должен ссылаться на каждый элемент массива и каждую переменную ответа правильно.

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 голосов
/ 17 января 2011

похоже, что ваш i неправильно закрыт

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

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

success: (function(i){
   return function(data,status,xhr){
     imageData.push([imageTemp[i], xhr.getResponseHeader('Content-Length')]);
   };
})(i)
1 голос
/ 17 января 2011

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

success: function(i){
    return function(message){
        imageData.push([imageTemp[i], ajaxSizeRequest.getResponseHeader('Content-Length')]);
    }
}(i)
0 голосов
/ 16 августа 2016

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

Информация: Есть ли причина использовать ключевое слово «var» в ES6? и: MDN - пусть синтаксис

0 голосов
/ 17 января 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...