1

I'm having problems with JavaScript logic. When we have a function that needs data from event-handler to generate result, is it possible to get that data back to function? For example, if we call Image() object or FileReader() inside and wait for its load event to get fired in order to generate proper return result.

Simple example:

function imageSize(filename) {
  funcResult = false;
  var img = new Image();
  img.onload = function() {
    myResult = { 
      width: img.width,
      height: img.height
      }
    }
  img.src = filename;
  return funcResult;
}

Course, it doesn't work because load fires asynchronously after function has already been executed. But is there some workaround to make function stop and listen which is my main goal.

Or bit more complex example (that also can't work for same reason).

function getImageSize(file) {
  res = false;
  if (window.FileReader) {
    var fileReader = new FileReader();
    fileReader.onload = function() {
      var img = new Image();
      img.onload = function() {
        res = {
          width  : img.width,
          height : img.height
          };
        }
      img.src = this.result;
      }
    fileReader.readAsDataURL(file);
  }
  return res;
}

Usage example:

var imageSize = getImageSize(myFileInput.files[0]);

and handling result as (perfect: wait)

if (!imageSize)
  console.log('error');
else
  console.log(imageSize.width + 'x' + imageSize.height);

or (alternative: from event handler)

imageSize.onload = function() {
  console.log(this.width + 'x' + this.height);
  }

I'd like to make this job linear (sync) and wait for proper event handlers inside to fire, not moving job outside of function scope (especially not to global level).

My goal is to make this a one-function job, or the worst case, to define some load event of that function and listen for result so my strict question is "is this somehow possible and if it is, how?"

I understand how events work and know well that this approach is wrong but that's just an illustration what I was trying to accomplish during last few days.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Wh1T3h4Ck5
  • 8,399
  • 9
  • 59
  • 79
  • Can always use a callback inside `imageSize` – tymeJV Apr 28 '15 at 20:08
  • @tymeJV thanks for suggestion. can you provide some simple example? not sure how to do that. – Wh1T3h4Ck5 Apr 28 '15 at 20:14
  • Check out the answer below... I had deleted it since it doesn't make the call *synchronous* - but I don't think you want that..just a way to manage what is happening. – tymeJV Apr 28 '15 at 20:15

1 Answers1

5

Use a callback inside your function to get the size:

function imageSize(filename, callback) {
    funcResult = false;
    var img = new Image();
    img.onload = function() {
        var myResult = { 
            width: img.width,
            height: img.height
        }
        callback(myResult)
    }
    img.src = filename;
}

And use it:

imageSize("test.jpg", function(sizeAttributes) {
    console.log(sizeAttributes);
});
tymeJV
  • 103,943
  • 14
  • 161
  • 157
  • oh thanks, I like how simple that looks like. can you drop a few words what exactly that `callback` do in that example. it's very important to me to understand how that works. it waits for img's `load` event to get fired right? – Wh1T3h4Ck5 Apr 28 '15 at 20:19
  • In JavaScript, you can pass anything as a parameter, including a function. Your images `onload` call is async, so everything inside the `onload` won't be processed until the image actually loads. A `callback` is a passed in function that will be ran once your async method has completed. A *much* more detailed callback explanation can be found here: http://stackoverflow.com/questions/9596276/how-to-explain-callbacks-in-plain-english-how-are-they-different-from-calling-o – tymeJV Apr 28 '15 at 20:25
  • good to know that. after a quick test seems that this is exactly my missing part (I have never user callback before). thanks a million. – Wh1T3h4Ck5 Apr 28 '15 at 20:30