【发布时间】:2018-03-02 14:13:34
【问题描述】:
我有以下文件选择器对话框。我想允许选择多个文件。选择文件后,我想呈现所选文件的预览。我的代码是:
<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})?
如果重要的话,所有这些代码都在一个反应文件中。
【问题讨论】:
-
不阻塞主线程是异步的。这可能会导致页面不响应,具体取决于文件大小。所以它不允许在页面中。但是 (FileReaderSync)[developer.mozilla.org/en-US/docs/Web/API/FileReaderSync] 存在,可在
workers中访问。 -
您可以在
onLoad回调和set previews中添加检查,如果所有文件都已读取。 -
如何在
onLoad回调中知道是否已读取所有文件。我无法将i或e.target.files.length传递给onLoad回调。即使我找到了传递索引和总长度的方法,我也无法可靠地知道所有文件都已读取。第 5 个文件读取可能会在第 3 个文件读取之前完成,等等。或者还有其他方法吗? -
你不必通过它。您可以在
function内访问i和e.target,因为它们在父范围内。 -
是的,我不必通过它们。我同意。但是如果第 5 次文件读取在第 3 次文件读取之前完成,我将无法知道所有文件读取都已完成(除非我维护某种可能导致重叠写入的 totalFilesRead 变量)。
标签: javascript reactjs asynchronous closures