1

I want to read some text files and sort them. I wrote the following function:

function load_files (event)
{
  var file;
  var reader;
  var lines = [];

  for (file of event.target.files)
  {
    reader = new FileReader();
    reader.onload = function (event)
    {
      let l = this.result.split (/\r?\n/); // lines to add
      for (let i = 0; i < l.length; i++)
        lines.push(l[i]);
    };
    reader.readAsText (file);
  }

  // how to wait for all onload functions here?

  replace_log(lines.sort());
}

Before I can sort the lines, I have to wait, that all loading has been finished. How can I wait for the asynchronous calls?

3
  • You can create a function that reads the file and returns a promise. Commented Feb 20, 2019 at 13:03
  • I have more than one file. Commented Feb 20, 2019 at 13:04
  • You can run all your promises through Promise.all then read the content of all your files Commented Feb 20, 2019 at 13:05

2 Answers 2

3

you can even count the occurrencies of the callback and trigger the sort when you read all files

function load_files (event) {
var file;
var reader;
var lines = [];
let count = 0;
for (file of event.target.files) {
    reader = new FileReader();
    // this event is triggered only in case of success
    reader.onload = function (event) {
      let l = this.result.split (/\r?\n/); // lines to add
      for (let i = 0; i < l.length; i++)
        lines.push(l[i]);
    };
    // this event is triggered both in case of success or failure when the op. is completed
    reader.onloadend = function(event) {
      if(++count === event.target.files.length)
        replace_log(lines.sort());
    }
    reader.readAsText (file);
  }
} 

or alternatively you can use Promises

function read_file(file) {
  return new Promise((resolve, reject) => {
    var fr = new FileReader();
    fr.onload = () => {
      resolve(fr.result);
    };
    fr.readAsText(file);
  });
}

function load_files(event) {
  var file;
  var reader;
  var lines = [];
  let count = 0;
  let promises = []; // collect all promises
  for (file of event.target.files) {
    promises.push(read_file(file));
  }

  Promise.all(promises) // wait for the resolutions
    .then(results => {
      for (result of results) {
        let l = result.split(/\r?\n/); // lines to add
        for (let i = 0; i < l.length; i++)
          lines.push(l[i]);
      }
      replace_log(lines.sort());
    })
}
Sign up to request clarification or add additional context in comments.

3 Comments

Looks pretty ugly.
i've added an alternative with promises :D
This looks buggy. result is a member of the event but not the file reader.
0

Thanks to Karim and his suggestion to use promises, I got it.

function load_files (event)
{
  Promise.all(
    (function* () {
      for (let file of event.target.files) {
        yield new Promise(resolve => {
          let reader = new FileReader();
          reader.onload = (event) => resolve(event.target.result);
          reader.readAsText(file);
        })}})())
    .then(texts => {
      let lines = [].concat.apply([], texts.map(text => text.split (/\r?\n/)));
      replace_log (lines.sort());
    });
}

Comments

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.