Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I am working on excel clone and had implemented feature of opening an excel sheet on the web using the following code but i do not understand the insides of the code very well as i am new to javascript .so please help me regarding the code . My code is -

<input type="file" onchange="readFile(this)">
<script>
function readFile(input) {
  let file = input.files[0];
  let reader = new FileReader();
  reader.readAsText(file);
  reader.onload = function() {
    console.log(reader.result);
  reader.onerror = function() {
    console.log(reader.error);
</script>

this works greatly but i do not get the asynch nature of it as i am aware that onLoad is sort of addeventListener which will be running in the browser APIs so when the load change occurs it will fire the callback function .

But what about reader.readAsText(file)?

My guess is it is reading the file asynchronously but if it is reading file in an Async manner why is there no callBack function attached to it which will run after it completes reading the file , as seen in the fs modules fileread() function where we have a specific callback to know that now file reading is complete or failed.

So please help me understand how reader.readAsText(file) this is async and whether it is async or not or it is just i am confusing two different scenarios completely altogther.

You should get comfortable reading the documentation for browser methods, such as developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsText – Andy Ray May 12, 2021 at 19:21

If you review the 'Event handlers' section of this API's MDN docs, you'll see that there are more than just the onload and onerror events that you could handle, such as onprogress. If the readAsText method took a callback argument, how would that one callback handle all of those potential events? When should that callback be invoked? Would that callback be invoked more than once?

Okay So readText is Async but since we have so many event handlers it is not a wise choice to provide readAsText with one callback ??RIght – Rohan Sharma May 13, 2021 at 9:53

This days FileReader have very little benefits now when we have new read methods on the blob (you would only need it for IE - which is mostly dead now)

If you are going to read binary (excel) files (and no ascii text files), then you can't read the content as text, b/c some encoding transformation will take place and make the string invalid, so you should actually read it as arrayBuffer

a modern approach that is asynchronous but feels synchronous would look something like this:

async function readFile (input) {
  const [file] = input.files
  if (!file) return // in case input have been cleared
  const buffer = await file.arrayBuffer()
  const uint8 = new Uint8Array(a)

(less code, no callbacks, and still async) (using the new read on blobs is preferred since it adds wider platform support on both Deno and NodeJS servers)

thanky u for your response. but that still does not clear my confusion on async nature . the code You mention simply consuming a promise with await keyword inside async function but my issue was why readAsText do not have a callback since it is an asynch function? – Rohan Sharma May 13, 2021 at 9:57
  • reader.readAsText(file) is something that is a synchronous code execution
  • So code after readAsText will actually run before reader.onload is being called
  • readAsText will just start another code execution and call some other function when something else happens
  • It's just structured in another way internally, instead of using a traditional callback function you have to register the function that you are interested for on some class instance. The FileReader has multiple "callback" functions (aka: eventlistener) that can be invoked after a delay and you don't need add a EventListener to all of them

  • onabort: (...)
  • onerror: (...)
  • onload: (...)
  • onloadend: (...)
  • onloadstart: (...)
  • onprogress: (...)
  • if you only need one or two of them (say: onload and onprogress) then it would be unnecessary to have to do apply arguments for each one of them: readAsText(file, ...noopFn, loadCallback, ...noopFn, progressCallback)

    It's the same thing with old XMLHttpRequest ajax method you don't add a callback when it returns the response you can listen for abortion, error, timeout, download & upload progress, state changed (when request have been open & sent, receive response header & body)

    Just b/c it dose not have a callback function dosen't mean that something is async or sync. It's the delay that defines something as async

    I mean [].forEach(callbackFn) has a callback function and it isn't async So those setTimeout(callbackFn, 1000) but this is async

    The part of what makes some function logic async is when a other function is being executed/or continued (in case of iterators & generators)... the question is: is it called immediately or after some delay? The readAsText is synchronous but the "logic" of getting the file content is asynchronous

    in other words if some function is not executed on the same call stack then it's considered as async

    Dose this make since?

    Oh and one more thing a FileReader instance can be reused more than once, so that you don't have to decleare the same error/callback functions again and again All doe you can't use it simultanas if it's already reading something. That is also one part of the reason why there isn't any callback arguments in the readAsText

    Thank you for adding that final point. The event handler assignments are for the instance, not for any particular method invocation. – Jared A Sutton May 13, 2021 at 17:16 i totally get your explanation except the part "The readAsText is synchronous but the "logic" of getting the file content is asynchronous" if it was sync function it had blocked the code before jumping to next line see this code . open.addEventListener("change", function () { // read as text fr.readAsText(fileObj); fr.addEventListener("load", function () { console.log(fr.result); }) console.log("After"); // ui init f }) on console it logs after before the text of file .and that happens only when a function is async that is it is delayed ? – Rohan Sharma May 14, 2021 at 8:37

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.