0

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 Answer 1

1

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);
    };
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you! Is there a way to keep it as an anonymous function?
@mila: The handler is an anonymous function. You don't want buildHandler to be one, because you want to reuse it. It's possible to make buildHandler anonymous and recreate it on every loop, but it's hard to debug and much less clear to read.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.