jquery load() in a loop

1.3k Views Asked by At

I'm trying to save dimensions of different images which are not present on the page but I use their url:

for (var i=0; i<media.length; i++)
{
    var temp_media={};
    var dim = {};

    $("<img/>")
        .attr("src", media[i].url)
        .load(function(){
            temp_media=
            {
                'type': media[i].type,
                'url': media[i].url,
                'src': media[i].source
            }

            dim['width']= this.width;
            dim['height']= this.height;
            temp_media['dimensions'] = dim;

            arr_media.push(temp_media);
    });
}

However, at the end of the loop I see that arr_media contains i images which are exactly the same and with the same dimensions (although their urls in media array are different).

I also tried to call the anonymous function with i like this:

$("<img/>")
    .attr("src", media[i].url)
    .load(function(i){   
        temp_media=
        {
            'type': media[i].type,
            'url': media[i].url,
            'src': media[i].source
        }

        dim['width']= this.width;
        dim['height']= this.height;
        temp_media['dimensions'] = dim;

        arr_media.push(temp_media);
}(i)); //sending i to the anonymous function

But then then for some reason "this" is the window object and not the image (I don't understand why).

I don't know which of the ways is in the right direction but I'd appreciate an advice for how to get it to work and an explanation for why in the 2nd trial "this" is not the image but the window.

Thank you!!

1

There are 1 best solutions below

2
On BEST ANSWER

The problem is that each of the success callbacks you're creating closes over the variable i, not the value of that variable when the callback was created. So they all see the value as of the end of the loop.

The usual answer is to use a builder function so the callback closes over something that doesn't change.

for (var i=0; i<media.length; i++)
{
    var temp_media={};
    var dim = {};

    $("<img/>")
        .attr("src", media[i].url)
        .load(buildHandler(media[i]));
}
function buildHandler(entry) {
    return function(){
            temp_media=
            {
                'type': entry.type,
                'url': entry.url,
                'src': entry.source
            }

            dim['width']= this.width;
            dim['height']= this.height;
            temp_media['dimensions'] = dim;

            arr_media.push(temp_media);
    };
}