javascript 如何使用 FileReader 的异步特性实现进度条和回调

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16443440/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 04:41:39  来源:igfitidea点击:

How to implement Progress Bar and Callbacks with async nature of the FileReader

javascripthtmlfilereader

提问by John

I have the FileReader API called within a for loop to iterate through multiple file objects. I'm using FileReader to essentially display preview of images.

我在 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
}

I'm bumping into two issues due to the async nature of the FileReader API. First, the onprogressevent fires for each FileReader instance. This gives me progress for each file. Whereas, I intend to display the total progress for all files instead of individual files.

由于 FileReader API 的异步性质,我遇到了两个问题。首先,onprogress为每个 FileReader 实例触发该事件。这给了我每个文件的进度。而我打算显示所有文件的总进度,而不是单个文件。

Secondly, I want to perform actions that should only be performed when all instances (one for each file) of the FileReader have completed. Currently, since FileReader is functioning asynchronously, the actions run before FileReader completes it's task. I have searched a lot and yet to come across a solution for these problems. Any help is appreciated.

其次,我想执行只有在 FileReader 的所有实例(每个文件一个)都完成时才应该执行的操作。目前,由于 FileReader 是异步运行的,操作在 FileReader 完成其任务之前运行。我已经搜索了很多,但尚未找到解决这些问题的方法。任何帮助表示赞赏。

回答by undefined

Let's address your second problem first. You need to define your after-completion code in a separate function, and call that function once all the files have uploaded:

让我们先解决您的第二个问题。您需要在单独的函数中定义完成后代码,并在所有文件上传后调用该函数:

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
}

Now, for tracking progress, there are a couple different ways you could address that. Right now you are loading all the files at once, and each file is reporting its own progress. If you don't mind less frequent progress updates, you could simply use the onload handler to report progress each time a file has uploaded. If you want really fine-grained, accurate progress updates, you are going to have to calculate the total size of all the files combined, then keep track of how much of each file has loaded, and use the sum of what has loaded for each file compared to the total size of all files to report progress.

现在,为了跟踪进度,有几种不同的方法可以解决这个问题。现在,您正在一次加载所有文件,并且每个文件都在报告自己的进度。如果您不介意不那么频繁地更新进度,您可以简单地使用 onload 处理程序在每次文件上传时报告进度。如果你想要真正细粒度、准确的进度更新,你将不得不计算所有文件的总大小,然后跟踪每个文件的加载量,并使用每个文件加载的总和文件与所有文件的总大小进行比较以报告进度。

Alternatively, assuming that you are implementing this with a progress bar rather than console.log, you could provide a separate progress bar for each file that's being uploaded, and calculate progress for each file exactly as you're doing it now, then updating the corresponding progress bar. Let me know if any of that needs clarification.

或者,假设您使用进度条而不是 console.log 来实现这一点,您可以为正在上传的每个文件提供一个单独的进度条,并完全按照您现在的方式计算每个文件的进度,然后更新对应的进度条。如果有任何需要澄清的地方,请告诉我。