代码之家  ›  专栏  ›  技术社区  ›  ceving

如何同步FileReader onload函数?

  •  0
  • ceving  · 技术社区  · 5 年前

    我想读一些文本文件并对它们进行排序。我编写了以下函数:

    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());
    }
    

    0 回复  |  直到 5 年前
        1
  •  2
  •   Karim    5 年前

    您甚至可以计算回调的发生率,并在读取所有文件时触发排序

    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);
      }
    } 
    

    或者你也可以用承诺

    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());
        })
    }
    
        2
  •  0
  •   ceving    5 年前

    Karim suggestion to use promises ,我知道了。

    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());
        });
    }