javascriptjqueryhtmlfileapi

Return variable from a reader.onload event


I am reading an array via JavaScript and saving the size of that array in a reader.onload event. I think that the reader.onload function is called when the file has finished uploading. event.target.result stores that array. I would like that array saved as a variable to be used in other functions but, I tried initializing an empty array and using the

slice 

function but, it didn't work. The console returns an undefined value.

Here is the code

<!DOCTYPE html>
<html>
<head>
    <title> Home Page </title>
</head>

<body>
    <input type="file" id="file" name="files[]" multiple/>
    <output id="list"></output>

    <p id="demo"></p>

    <script>
      function handleFileSelect(evt) { 
        // grab the file that was uploaded which is type File. 
        // evt is the event that was triggered
        // evt.target returns the element that triggered the event 
        // evt.target.files[0] returns the file that was uploaded, type File
        var file = evt.target.files[0]; 

        var myArray = [];
        // instantiate a FileReader object to read/save the file that was uploaded
        var reader = new FileReader();
          // when the load event is fired (the file has finished uploading) this function is called
        reader.onload = function(event) {
          // the result attribute contains an ArrayBuffer representing the file's data. 
          var arrayBuffer = event.target.result;
          myArray = arrayBuffer.slice(0);
          document.getElementById("demo").innerHTML = arrayBuffer.byteLength;
        }

        // read the file and save as an array. Once the read is finished loadend is triggered
        reader.readAsArrayBuffer(file);
        console.log(myArray.byteLength);
      }

      //console.log(myArray.byteLength);
      document.getElementById('file').addEventListener('change', handleFileSelect, false);
    </script>
</body>


Solution

  • onload happens asynchronously. So whatever logic depends on myArray needs to happen within that onload function.

        reader.onload = function(event) {
          var arrayBuffer = event.target.result;
          var myArray = arrayBuffer.slice(0);
          document.getElementById("demo").innerHTML = arrayBuffer.byteLength;
    
          // this needs to happen here
          console.log(myArray.byteLength);
        }
    
        reader.readAsArrayBuffer(file);
    

    This is very, very similar to the often asked question (regarding AJAX/async callbacks) How to return value from an asynchronous callback function?

    By the way, this is asynchronous because we don't want to block the entire user interface while waiting for the potentially long operation of reading a file. That's why we're using an onload handler here.