Ajax HEAD request via Javascript/jQuery

52,729

Solution 1

The problem is that the single variables i and ajaxSizeRequest being captured by the callback function are the same variables for all instances of the callback function. I think if you call a function and pass the index variable to it and, at the same time, scope the request variable locally to the function itself use the response parameter of the done handler, you should end up with independent variables captured by the callback. It should then reference each array element and each response variable correctly.

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

Solution 2

looks like your i isnt properly closed-in

in addition, you can't use ajaxSizeRequest because it too is pointing to just one request (probably the last, because the loop will execute very fast)

just wrap your success callback function as follows, changing the reference to ajaxSizeRequest:

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

Solution 3

You can scope I like so:

success: function(i){
    return function(message){
        imageData.push([imageTemp[i], ajaxSizeRequest.getResponseHeader('Content-Length')]);
    }
}(i)
Share:
52,729
Dan Lugg
Author by

Dan Lugg

… 60% of the time, it works every time.

Updated on August 17, 2020

Comments

  • Dan Lugg
    Dan Lugg almost 4 years

    I seem to be having some issues with making HEAD requests, and preserving the integrity of data in an array.

    Given this snippet:

    var imageTemp = Array();
    
    $('*')
        .each(function(index){
            if($(this).css('background-image') != 'none'){
                imageTemp.push($(this).css('background-image').slice(5, -2));
            }
        });
    

    I capture the URLs of all background-images on a given page. Now, trying to grab the size of each image via HEAD requests for Content-Length, I use this snippet:

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

    However, when I dump imageData via console.log, I each element (which should be an array containing the URL and the content-length) ends up as [undefined, XXXX] where XXXX is always the size of the last requested Content-Length

    I'm stumped, though it appears to be a timing/scoping issue. Do I have a sort of race-condition occuring here?

  • Dan Lugg
    Dan Lugg over 13 years
    Thanks alot tvanfosson; That works like a charm. I made updateImageData anonymous to avoid pollution of my script.
  • Admin
    Admin about 9 years
    avoid using success, prevent code-clutter!, use .done(function(text, status, xhr){ ...... }; instead.
  • tvanfosson
    tvanfosson about 9 years
    @EladKarako - pretty old answer, I've updated to reflect current best practice.
  • Admin
    Admin about 9 years
    thanks for the update, b.t.w, answer(s) are timeless ;) (.....well.. at-least as long Google will suggest it in the first 5 results).