2

I am struggling a bit with asynchronous operations and Promises (a quite new concept to me) using FileReader. I have found a very interesting thread about it there, but can't make my script to work despite this great content.

I have a file input accepting multiple files, I want to read those files and push their content into an array. But it seems I am not quite understanding well how a promise works because I still get an empty array at the end.

const inputElement = document.getElementById("trackfiles");
inputElement.addEventListener("change", (e) => {
  const selectedFiles = inputElement.files;

  let p = Promise.resolve();
  for (const file of selectedFiles) {
    p = p.then(() =>
      readAsData(file).then((content) => {
        files_content.push(content);
      }),
    );
  }

  console.log(files_content);
});

function readAsData(file) {
  return new Promise((resolve, reject) => {
    let reader = new FileReader();
    reader.readAsText(file);
    reader.onload = () => {
      resolve(reader.result);
    };
    reader.onerror = reject;
  });
}

When I select files, I get an empty array:

Chrome dev tools log

Thank you for your help

1 Answer 1

1

You are printing the array before the asynchronous then callbacks have executed.

You need to await the resolution of the promises before printing the array.

So replace this:

  console.log(files_content);

with this:

  p.then(() => console.log(files_content));

Unrelated to your question, but you don't have to wait to have read one file before starting to read the next. You could call readAsData for all selected files without delay, and then await all promises you get returned for them with Promise.all.

Secondly, things may look cleaner when you make use of the async/await syntax:

inputElement.addEventListener("change", async (e) => {
  const files_content = await Promise.all(Array.from(inputElement.files, readAsData));
  console.log(files_content);
});
Sign up to request clarification or add additional context in comments.

2 Comments

I took the async/await route. And I now understand why I didn't get the proper result now, since my console.log was still in the call stack, it was executed before the promise. Thank you @trincot
Good to hear it makes sense. Just one tiny adjustment: promises don't execute. They transition state (to resolved or rejected). What executes is the callback you pass to the then method.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.