FileReader:使用javascript读取许多文件而不会发生内存泄漏

cec*_*mel 5 javascript file

在网页中,我必须读取文件的一小部分,对于许多(1500-12000)小文件来说,每个文件的大小约为1 Mb。收集所需信息后,将其推回到服务器上。

我的问题:我使用FileReader API,垃圾收集无法正常工作,并且内存消耗激增。

代码如下:

function extract_information_from_files(input_files) {

//some dummy implementation
for (var i = 0; i < input_files.length; ++i) {


    (function dummy_function(file) {

        var reader = new FileReader();

        reader.onload = function () {

            //convert to Uint8Array because used library expects this

            var array_buffer = new Uint8Array(reader.result);

            //do some fancy stuff with the library (very small subset of data is kept)

            //finish

            //function call ends, expect garbage collect to start cleaning.
            //even explicit dereferencing does not work
        };

        reader.readAsArrayBuffer(file);

    })(input_files[i]);

}
Run Code Online (Sandbox Code Playgroud)

}

一些说明:

当结合使用FileReader和https://gildas-lormeau.github.io/zip.js/时,最后一个奇怪的细节(为完整性而发布),我在将文件推送到zip存档之前读取了文件,垃圾收集才可以正常工作。

所有这些说明似乎都指向我无法使用FileReader,因此请告诉我如何使用。

m4k*_*tub 3

该问题可能与执行顺序有关。在您的for循环中,您正在读取所有带有reader.readAsArrayBuffer(file). onload该代码将在为读者运行任何代码之前运行。根据浏览器的实现,这可能意味着浏览器在调用FileReader任何文件之前加载整个文件(或者简单地为整个文件预分配缓冲区) 。onload

尝试像队列一样处理文件,看看是否有区别。就像是:

function extract_information_from_files(input_files) {
    var reader = new FileReader();

    function process_one() {
        var single_file = input_files.pop();
        if (single_file === undefined) {
            return;
        }

        (function dummy_function(file) {
            //var reader = new FileReader();

            reader.onload = function () {
                // do your stuff
                // process next at the end
                process_one();
            };

            reader.readAsArrayBuffer(file);
        })(single_file);
    }

    process_one();
}

extract_information_from_files(file_array_1);
// uncomment next line to process another file array in parallel
// extract_information_from_files(file_array_2);
Run Code Online (Sandbox Code Playgroud)

编辑:浏览器似乎希望您重用FileReaders。我编辑了代码以重用单个阅读器,并测试(在 Chrome 中)内存使用量仍仅限于您读取的最大文件。