Чтение нескольких файлов с помощью JavaScript и ожидание результата - PullRequest
0 голосов
/ 23 мая 2018

Я хотел бы начать с того, что (исходя из c ++ и python) я совершенно новичок в JS и поэтому приветствую любые мудрые предложения, касающиеся моего кода.

Я хочу прочитать несколько файлов с помощью файлового API HTML5, затем открыть их с помощью 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 голосов
/ 23 мая 2018

Попробуйте прочитать класс 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
    });
}

Это всего лишь приблизительная схема решения.Я бы посоветовал вам сначала немного поэкспериментировать с Обещаниями (это может быть довольно глубокая тема), чтобы выяснить основные принципы, а затем применить что-то подобное выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...