1

so i want store the dataURl of a file outside the reader.onload function but when i assign it to a variable hello and try to print it , it still remins undefined.

here is the code

<input type='file' accept='image/*' onchange='openFile(event)'><br>
<img id='output'>
<script>
  var openFile = function(event) {
    var input = event.target;

    var reader = new FileReader();
    reader.onload = function(){
      var dataURL = reader.result;
      var output = document.getElementById('output');
      output.src = dataURL;

    };
    reader.readAsDataURL(input.files[0]);
    var hello=reader.result;
    console.log(hello);
    console.log(reader.result);
  };
</script>

but the same reader.result can be printed from inside the the on load function

i want a way to store the dataURL of the file outside the reader.onload function so that i can use it for future use anyway possible ?

  • you are missing scope here dataURL is local to anonymous function for load...trying to access outside it will cause undefined error...declare dataURL at the top and try – RohitS Oct 05 '16 at 20:07
  • That will not help because the line where dataURL is set is executed _after_ we try and use its value. – jacobianism Oct 05 '16 at 20:16

2 Answers2

2

Here is your script with some logging pointing out the order things will run:

var openFile = function(event) {
    console.log("1. onchange triggered");

    var input = event.target;

    var reader = new FileReader();

    console.log("2. Set handler for onload event");
    reader.onload = function(){
      console.log("5. onload handler called. Now the file is ready");
      var dataURL = reader.result;
      var output = document.getElementById('output');
      console.log("6. Set img src to image");
      output.src = dataURL;

    };
    console.log("3. Start reading file");
    reader.readAsDataURL(input.files[0]);

    console.log("4. Try to look at the file read result, even though the file has not finished being read yet...");
    var hello=reader.result;
    console.log(hello);
    console.log(reader.result);
 };

JS fiddle: https://jsfiddle.net/ncwv0ocL/1/

The problem is that readAsDataURL starts loading the file in the background, while the rest of your code executes. You can only get the result after the onload handler has been called.

One option to make it a bit clearer might be to do something like this:

var openFile = function(event) {
    var input = event.target;
    var reader = new FileReader();
    reader.onload = fileLoaded; // Tell the FileReader to call this function when the file is loaded
    reader.readAsDataURL(input.files[0]);

    // Code here should not depend on the state of the FileReader
 };

var fileLoaded = function (event) {
    var dataURL = event.target.result; // The event parameter gives us the target of the event (the FileReader)
    var output = document.getElementById('output');
    output.src = dataURL;

    // Do your other stuff here with dataURL
    console.log(dataURL);
};

One thing I like about this is that the code gets executes in the order it appears on the page :)

See it in action here: https://jsfiddle.net/ncwv0ocL/2/

jacobianism
  • 226
  • 1
  • 3
  • 12
0

The problem is trying to view the result after the reader is finished. The solution would be to call a function from our reader's onload that would provide any functionality we need, i.e. updating our output field.

var openFile = function(e) {

    var input = e.target
    var reader = new FileReader()

    // Our doSomething function would do whatever is needed after we get our value.
    // This allows us to dynamically update anything as opposed to having to check a value to see if it has been updated

    var doSomething = function(dataURL) {

        var output = document.getElementById('output')

        output.src = dataURL

        console.log(dataURL)

    }

    reader.onload = function() {

        // Once we have the data, we pass it to our action that will control what we do with the result

        doSomething(reader.result)

    }

    reader.readAsDataURL(input.files[0]);

}

So, our process becomes Upload File >> Read File >> Notify Application

Here is an example of the solution on CodePen

Lance Jernigan
  • 226
  • 2
  • 6