Подтвердить что ты не робот

Запрос 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

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

4b9b3361

Ответ 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.