我在 for 循环中调用了 FileReader API,以迭代多个文件对象。我使用 FileReader 本质上是显示图像预览。
function() {
for (var i in Files) {
var fileReader = new FileReader();
fileReader.readAsBinaryString(Files[i]);
fileReader.onload = function() {
// do something on FileReader onload
}
fileReader.onprogress = function(data) {
if (data.lengthComputable) {
var progress = parseInt( ((data.loaded / data.total) * 100), 10 );
console.log(progress);
}
}
}
// do something on completion of FileReader process
// actions here run before completion of FileReader
}
由于 FileReader API 的异步特性,我遇到了两个问题。首先,每个 FileReader 实例都会触发
onprogress
事件。这给了我每个文件的进度。然而,我打算显示所有文件而不是单个文件的总进度。
其次,我想执行仅当 FileReader 的所有实例(每个文件一个)完成时才应执行的操作。目前,由于 FileReader 是异步运行的,因此操作会在 FileReader 完成其任务之前运行。我进行了很多搜索,但尚未找到解决这些问题的方法。如有任何帮助,我们将不胜感激。
让我们先解决你的第二个问题。 您需要在单独的函数中定义完成后代码,并在所有文件上传后调用该函数:
function() {
var total = Files.length; loaded = 0;
for (var i in Files) {
var fileReader = new FileReader();
fileReader.readAsBinaryString(Files[i]);
fileReader.onload = function() {
// do something on FileReader onload
loaded++;
if (loaded == total){
onAllFilesLoaded();
}
}
fileReader.onprogress = function(data) {
if (data.lengthComputable) {
var progress = parseInt( ((data.loaded / data.total) * 100), 10 );
console.log(progress);
}
}
}
}
function onAllFilesLoaded(){
//do stuff with files
}
现在,为了跟踪进度,您可以通过几种不同的方法来解决这个问题。 现在您正在一次加载所有文件,并且每个文件都报告自己的进度。 如果您不介意进度更新频率较低,则可以简单地使用 onload 处理程序在每次文件上传时报告进度。 如果您想要真正细粒度、准确的进度更新,则必须计算所有文件组合的总大小,然后跟踪每个文件已加载的量,并使用每个文件已加载的总和文件与所有文件的总大小进行比较以报告进度。
或者,假设您使用进度条而不是 console.log 来实现此操作,您可以为每个正在上传的文件提供一个单独的进度条,并按照您现在所做的那样计算每个文件的进度,然后更新相应的进度条。 如果有任何需要澄清的地方,请告诉我。