使用JavaScript读取多个文件并等待结果

时间:2018-05-23 10:25:26

标签: javascript html html5 filereader

我想先说(来自c ++和python)我对JS很新,所以我欢迎任何关于我的代码的明智建议。

我希望使用HTML5文件API读取一些文件,然后用JS打开它们,执行一些操作并下载压缩的结果。我的问题是,读取文件似乎是一个异步操作,我真的没有看到一种优雅的方式等待它们全部完成然后压缩结果。

此处提供了一种可能的解决方案: https://stackoverflow.com/a/17491515 但我想知道一个人是否可以比使用全球旗帜更好。

我也遇到了从异步函数中检索结果的问题,因为我不知道如何在new_file_list中找回changeCharsInFiles

谢谢!

代码示例: HTML:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    </head>
    <body >
        <div class="container">
            <div class="jumbotron">
                <h3>Add Files Here</h3>
                <input type="file" id="the-file-field" multiple>
            </div>
        </div>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.5/jszip.min.js"></script>
        <script src="http://cdn.jsdelivr.net/g/filesaver.js"></script>
        <script>
         ########### SEE JS BELOW #####################
    </script>
</body>

JS:

if (window.File && window.FileReader && window.FileList && window.Blob) {

                //functions
                function zipMyFilesAndSave(file_list){

                    var zip = new JSZip();
                    for (var i = 0; i<file_list.length; i+=1)
                    {
                        zip.file(file_list[i].name, file_list[i]  );
                    }
                    zip.generateAsync({type:"blob"}).then(
                    function (blob) {                                      
                        saveAs(blob, "hello.zip");                         
                    }, 
                    function (err) {
                        jQuery("#blob").text(err);
                    }); 
                }

                function changeCharsInFiles(file_list){
                    var new_file_list = [];

                    for (var i = 0; i<file_list.length; i+=1)
                    {
                        var file = file_list[i]

                        var reader = new FileReader();
                        reader.onload = function() {
                            //alert(reader.result);
                            var txt  = reader.result;
                            console.log("txt: ",txt)

                            var new_txt = ""
                            var allTextLines = txt.split(/\r\n|\n/);

                            for (var j = 0; j<allTextLines.length; j+=1)
                            {
                                var res = allTextLines[j].replace("a", "A");
                                res = res.replace("b", "B");
                                res = res.replace("c", "C");
                                res = res.replace("d", "D");

                                new_txt += res + "\n"

                            }
                            console.log("new_txt: ", new_txt)
                            var new_file = new Blob([new_txt], {type: "text/plain"});

                            new_file_list.push(new_file); //<---------------------------how do I get this back?
                        }
                        reader.readAsText(file);    

                    }


                    return new_file_list;
                }

                //watcher
                $( "#the-file-field" ).change(function() {
                    console.log("files have been chosen")
                    var file_list = this.files
                    file_list = changeCharsInFiles(file_list)
                    zipMyFilesAndSave(file_list)    
                });


            } else {
                alert('The File APIs are not fully supported in this browser.');
            }

1 个答案:

答案 0 :(得分:3)

尝试阅读Promise类,开发它是为了简化异步操作:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

在您的情况下,您可以像这样使用它:

function changeCharsInFiles(file_list){
    let promises = [];
    for (let file of file_list) {
        let filePromise = new Promise(resolve => {
            let reader = new FileReader();
            reader.readAsText(file);
            reader.onload = () => resolve(reader.result);
        });
        promises.push(filePromise);
    }
    Promise.all(promises).then(fileContents => {
        // fileContents will be an array containing
        // the contents of the files, perform the
        // character replacements and other transformations
        // here as needed
    });
}

这只是解决方案的大致轮廓。我建议你首先尝试使用Promise(这可能是一个相当深刻的主题)来弄清楚基本原理,然后应用类似上面的内容。