-1

I am super confused why Line 2 is executing before Line 1.

I have a function base64 to convert uploaded files into base64. Then I am calling the function base64, and then trying to put the base 64 into a variable. However, the flow is going upside down and not working. Why is the line 2 executing before line 1

  function base64(file, callback) {
    var coolFile = {};

    function readerOnload(e) {
      var base64 = btoa(e.target.result);
      coolFile.base64 = base64;
      callback(coolFile);
    }

    ;
    var reader = new FileReader();
    reader.onload = readerOnload;
    var file = file[0].files[0];
    coolFile.filetype = file.type;
    coolFile.size = file.size;
    coolFile.filename = file.name;
    reader.readAsBinaryString(file);
  }

        var fileToSend;

        base64($('input[type="file"]'), function (filedata) {
          var convertedFile = filedata.base64;
          console.log('\n file SB1 \t' + convertedFile);
          fileToSend = convertedFile;
          console.log ('Line 1 \t' + fileToSend);
        });

        console.log('\n Line 2 \t' + fileToSend);
Hello Universe
  • 3,248
  • 7
  • 50
  • 86
  • "Line 2" is executed synchronously whereas "Line 1" is executed asynchronously and async code is executed _after_ synchronous code has executed. – Yousaf Jul 05 '21 at 07:12
  • Which line is executing before which line? – Nitheesh Jul 05 '21 at 07:13
  • The lines are printed in the console.log.. It is at the end – Hello Universe Jul 05 '21 at 07:14
  • @Yousaf How can I make it flow top down? – Hello Universe Jul 05 '21 at 07:14
  • 1
    It is already top down. Callback function passed to function `base64` is invoked at some later time, _after_ the `base64` function has already executed and "Line 2" has also executed. – Yousaf Jul 05 '21 at 07:18
  • 2
    If you need to do stuff after the async operation has finished - then do it inside the callback function, that’s what those are for. If you don’t want that, then you need to go look into stuff like `await` and promises, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await – CBroe Jul 05 '21 at 07:19

2 Answers2

2

Your 'Line 1' statement is part of a callback passed to base64 function. Inside that function you put that callback into another function readerOnload(), which is called after FileReader load event fires (reader.onload = readerOnload;).

Your file needs some time to get loaded into FileReader, and this process is asynchronous, so the Task Queue moves to 'Line 2' before that happens.

To understand better what's happening here check out this video: https://www.youtube.com/watch?v=8aGhZQkoFbQ

Danny Matkovsky
  • 662
  • 4
  • 14
1

Here is a fixed version of your code

Your original code was incomplete and had the async issue mentioned in the comments

function base64(file, callback) {
  var coolFile = {};

  function readerOnload(e) { console.log(e.target.result)
    var base64 = btoa(e.target.result);
    coolFile.base64 = base64;
    callback(coolFile);
  }

  ;
  var reader = new FileReader();
  reader.onload = readerOnload;
  var file = file[0].files[0];
  coolFile.filetype = file.type;
  coolFile.size = file.size;
  coolFile.filename = file.name;
  reader.readAsBinaryString(file);
}

$('input[type="file"]').on("change", function() {
  base64([this],
    function(filedata) {
      var convertedFile = filedata.base64; // file to send
      console.log('\n file SB1 \t' + convertedFile);
    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="file" />
mplungjan
  • 169,008
  • 28
  • 173
  • 236