2

I've got a function to detect the size of an image, and I want it to return an object that contains both the width and height. In the code below, sz.width and sz.height within the function hold the values, but after they return the value it's undefined. What am I missing?

     function getImgSize(imgSrc) {
        var newImg = new Image();

        newImg.onload = function() {
          var height = newImg.height;
          var width = newImg.width;

          function s() {}
          sz = new s();
          sz.width = width;
          sz.height = height;
          $('#infunc').text("in function, w = "+sz.width+", h = "+sz.height);
          return sz;
        }
        newImg.src = imgSrc; // this must be done AFTER setting onload
      }

var sz = getImgSize("http://lorempixel.com/output/fashion-q-c-1920-1920-4.jpg");
$('#outfunc').text("outside function, w = "+sz.width+", h = "+sz.height);

jsfiddle: http://jsfiddle.net/forgetcolor/LbxA3/

3
  • 2
    You are not the first to try to use async code in sequential context. Not the last either :) Commented May 22, 2012 at 1:49
  • Besides that you don't return anything, won't the image load function run after the image has been loaded, whereas getImgSize would return before then? (I'm not sure how the image loading stuff works.) Commented May 22, 2012 at 1:50
  • This question is similar to: How do I return the response from an asynchronous call?. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem. Commented Oct 16 at 13:35

2 Answers 2

3

The function getImgSize sets up the image loading and then terminates. Later, when the image loads, the anonymous onload function is invoked and correctly calculates the size, then returns it, to an uncaring DOM engine...

You're probably wondering how you can do what you want. Short answer: you can't. Here's the closest you can get:

  function getImgSize(imgSrc, callback) {
    var newImg = new Image();

    newImg.onload = function() {
      ... // blah-blah blah
      callback(sz);
    }
    newImg.src = imgSrc;
  }
  getImgSize("http://lorempixel.com/output/fashion-q-c-1920-1920-4.jpg",
            function(sz) {
              $('#outfunc').text("in callback, w = "+sz.width+
                                 ", h = "+sz.height);
            });

I actually came here to write:

// this must be done AFTER setting onload

That's what I bet your problem was. // this must be done AFTER setting onload

Sign up to request clarification or add additional context in comments.

Comments

2

It can't be done. You're trying to get a return value of an async call.

Consider:

var i = 0;
setTimeout(function() { i = 1; }, 1000); //1 second later
alert(i);

That will alert 0 because the value only gets changed in one second and not right away.

don't believe me?

What you're trying to do is the same thing. you can't use a value that didn't happen yet. In order to accomplish what you're trying to, you need to use callbacks.

Comments

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.