【问题标题】:FileReader memory leakFileReader 内存泄漏
【发布时间】:2015-08-19 17:52:42
【问题描述】:

我正在使用 FileReader 将图像文件上传到客户端 用于数据获取和缩略图显示。

我注意到的是, 在页面进程中,在任务管理器中, 内存只会越来越高。 当进程停止时,内存保持高位并且永不下降。

你能告诉我我在这里做错了什么吗?

要查看,请上传200多张图片,最多30MG。 并看到内存一直在泄漏

先谢谢你了。

-- here is a link to a code example on the web

这是我的代码:

<input class="fu" type="file" multiple="multiple" />
<div class="fin"></div>
<div class="list"></div>

<script type="text/javascript">
    $(document).ready(function () {
        var input = $("body input.fu");

        input[0].addEventListener('change', fu.select, false);
    });

    var fu = {
        list: [],
        index: 0,

        select: function (evt) {
            evt.stopPropagation();
            evt.preventDefault();

            var files = evt.target.files ? evt.target.files : evt.dataTransfer ? evt.dataTransfer.files : []; // FileList object

            fu.list = files;
            fu.index = 0;

            fu.load();
        },

        load: function () {
            var index = fu.index;
            var file = fu.list[index];

            if (file) {
                var reader = new FileReader(); // File API object

                reader.onloadend = (function (theFile) {
                    return function (evt) {
                        if (evt.target.readyState == FileReader.DONE) {
                            setTimeout(fu.load, 20);
                        }
                    };
                })(file);


                reader.onprogress = null;
                reader.onloadstart = null;
                reader.onerror = null;
                reader.onabort = null;

                if (reader.readAsBinaryString) {
                    reader.readAsBinaryString(file);
                } else {
                    reader.readAsDataURL(file);
                }

                fu.index++;
                $('.fin').html("#" + fu.index);
            } else {
                $('.fin').html("finish");
            }

        }
    }
</script>

【问题讨论】:

  • "要检查,请上传超过 200 张图片" 创建 200 个 FileReader 实例? “最多30MG。”什么是“MG”?
  • 它是创建 200 个实例吗? MG是兆字节,想法是上传许多图像到客户端并查看对内存的影响。如果您上传 10 张图片,您不会看到不同的
  • 尝试打开任务管理器,选择当前选项卡,在jsfiddle.net/uynvenL9查看内存
  • 我有一种强烈的感觉,那就是你的 reader.onloadend 函数......我真的不明白你想在那里做什么?
  • onloadend - 我得到了我需要获取数据并显示缩略图的文件流。在这里我已经表明,即使我什么都不做,只加载一个文件然后下一个文件,它仍然会弄乱内存@MinusFour

标签: javascript html memory-leaks filereader


【解决方案1】:

好的,我已经解决了这个问题。

原因是我每次都将 reader 设置为 - new FileReader()。

所以我只将它设为全局。

这是工作代码:

<script type="text/javascript">
    $(document).ready(function () {
        var input = $("body input.fu");

        input[0].addEventListener('change', fu.select, false);
    });

    var fu = {
        list: [],
        index: 0,
        reader: null,

        select: function (evt) {
            evt.stopPropagation();
            evt.preventDefault();

            var files = evt.target.files ? evt.target.files : evt.dataTransfer ? evt.dataTransfer.files : []; // FileList object

            fu.list = files;
            fu.index = 0;

            fu.reader = new FileReader(); // <- made this only once

            fu.load();
        },

        load: function () {
            var index = fu.index;
            var file = fu.list[index];

            if (file) {
                fu.reader.onloadend = (function (theFile) {
                    return function (evt) {
                        if (evt.target.readyState == FileReader.DONE) {
                            fu.reader.abort();

                            setTimeout(fu.load, 5);
                        }
                    };
                })(file);


                fu.reader.onprogress = null;
                fu.reader.onloadstart = null;
                fu.reader.onerror = null;
                fu.reader.onabort = null;

                if (fu.reader.readAsBinaryString) {
                    fu.reader.readAsBinaryString(file);
                } else {
                    fu.reader.readAsDataURL(file);
                }

                fu.index++;
                $('.fin').html("#" + fu.index);
            } else {
                $('.fin').html("finish");
            }

        }
    }
</script>

【讨论】:

    【解决方案2】:

    我刚刚用 289 个文件对其进行了测试,并且没有内存泄漏。这是我使用的 jsfiddle:

    http://jsfiddle.net/2pyqjeke/

    阅读前:

                  total        used        free      shared  buff/cache   available
    Mem:           3945        1400         749          23        1796        2253
    

    看完后:

                  total        used        free      shared  buff/cache   available
    Mem:           3945        1963         292          23        1690        1690
    

    不久之后:

                  total        used        free      shared  buff/cache   available
    Mem:           3945        1398         856          23        1690        2255
    

    我正在使用 Firefox 和 Manjaro。

    编辑

    对于 Chromium,这些是我的结果。

    之前:

                  total        used        free      shared  buff/cache   available
    Mem:           3945        1140         633          52        2171        2476
    

    加载图片后:

                  total        used        free      shared  buff/cache   available
    Mem:           3945        1573         296          43        2075        2050
    

    之后它就不会崩溃了……所以我猜 GC 并没有释放文件阅读器。所以我对代码做了一个很小的改动:

    http://jsfiddle.net/2pyqjeke/1/

    这是 Chromium 中的结果......

    之前:

                  total        used        free      shared  buff/cache   available
    Mem:           3945        1197         672          44        2075        2426
    

    加载图片后:

                  total        used        free      shared  buff/cache   available
    Mem:           3945        1588         322          44        2034        2035
    

    过了一会儿,它变成了:

                  total        used        free      shared  buff/cache   available
    Mem:           3945        1227         684          44        2034        2397
    

    坦率地说,我不明白为什么 Chromium 不发布 FileReader 而 Firefox 是。

    【讨论】:

    • 请尝试使用 chrome。您要上传大文件吗?
    • @RoeyZada,我已经用 Chromium 更新了答案并添加了一个可能的修复方法。
    • 谢谢! ..不幸的是,这仍然没有释放我在chrome上的内存。在 Firefox 中,它就像一个魅力。
    • 我注意到它不会立即释放资源...我不知道为什么。大约需要一分钟左右,但它确实在 Chrome 上释放了大部分内容,并且在 Firefox 上完美运行。
    • 我终于找到了解决办法。看看我的回答,原因是让阅读器只有一个 - new FileReader() - 现在它对于 Firefox 和 chrome 都没有上升! .. 非常感谢您的帮助 :) @MinusFour
    猜你喜欢
    • 2017-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-08
    • 2013-01-20
    • 2011-10-31
    • 2019-08-10
    • 2013-06-24
    相关资源
    最近更新 更多