首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Javascript中读取的同步文件

Javascript中读取的同步文件
EN

Stack Overflow用户
提问于 2017-09-21 09:31:08
回答 2查看 88关注 0票数 0

我有下面的文件选择器对话框。我希望允许选择多个文件。选定文件后,我要呈现所选文件的预览。我的代码是:

代码语言:javascript
复制
<input
          type="file"
          multiple
          accept=".png, .jpeg"

          onChange={e => {
            this.setState({ previews: [] });

            if (!e.target.files) {
              return;
            }

            var previews = [];

            for (var i = 0; i < e.target.files.length; i++) {
              var file = e.target.files[i];
              (function(file, previews) {
                var reader = new FileReader();

                reader.onload = function(e) {
                  // console.log(e.target.result);
                  console.log("Just pushed a new preview");
                  previews.push(e.target.result);
                };
                reader.readAsDataURL(file);
              })(file, previews);
            }

            console.log("All files read");
            // I want this to be called only after
            // all the file contents are read
            this.setState({ previews });
          }}
        />

但是,使用上面的代码,我的Just pushed a new preview是在控制台上打印All files read之后打印出来的。

有什么方法可以让FileReader循环(闭包)完成,然后调用this.setState({previews})吗?

如果重要的话,所有这些代码都在一个react文件中。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-09-21 10:12:24

您需要在setState事件中移动onLoad。由于文件读取器是异步的,所以onLoad之外的设置状态将在事件完成之前触发它,并将导致空的或不完整的previews数组。

代码语言:javascript
复制
 var previews = [];
 var s = this;

 for (var i = 0; i < e.target.files.length; i++) {
   var file = e.target.files[i];
      var reader = new FileReader();

      reader.onload = function(e) {
        previews.push(e.target.result);
        s.setState({ previews });
      };

      reader.readAsDataURL(file);
 }
票数 0
EN

Stack Overflow用户

发布于 2017-09-21 15:48:18

使用Promise.all等待完成所有承诺,以知道是否处理了所有文件。而且,您需要在读取完文件后立即更新状态。最好添加一个进度条和setState来更新它。

代码语言:javascript
复制
var Sample = React.createClass({
  getInitialState: function () { return { previews: [], allfilesdone:false }; }, 
  render: function() {
    var p = this.state.previews.map((p) => <div>{p}</div>);
    return (
      <div style = {this.styler}>
        <input id="upload" multiple
          accept=".txt" type="file"
           onClick={(e) => this.setState({allfilesdone: false})}
           onChange={(event)=> { 
                var s = this;
                this.setState({previews:[], allfilesdone: false});
                var fs = event.target.files;
                Promise.all([...fs].map((file) => {
                  var reader = new FileReader();
                  return new Promise((resolve,reject) => {
                    reader.onload = (ev) => {
                        resolve(ev.target.result);
                        var pt = this.state.previews;
                        pt.push(ev.target.result);
                        s.setState({previews: pt});
                    }
                    reader.readAsText(file);
                  });
                }))
                  .then(ft => {
                        this.setState({allfilesdone: true});
                      });
            }}/>
        <div>all processed: {this.state.allfilesdone?"true":"false"}</div>
        <div>number of files: {this.state.previews.length}</div>
        <div>{p}</div>
      </div>
    );
  }
});

React.render(
  <Sample />, 
  document.getElementById('mount-point'));
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46340315

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档