39

webkit中有一个已知错误,即当您从 DOM 中删除图像时,它不会释放与其关联的内存。

这是经常加载图像的单页应用程序的问题。

各种建议的解决方案是:

前 3 种方法对我不起作用。回收图像元素的主要缺点是它意味着要编写大量代码来管理它。我正在通过 AJAX 加载可能包含图像的新 HTML,因此我不一定知道将加载的图像数量。

是否有其他解决方法来解决此问题?

4

5 回答 5

13

我使用了 3 种不同类型的方法...

首先。确实添加了一组图像并将垃圾收集留给浏览器。 在此处输入图像描述

它肯定是垃圾收集,但过了一段时间,确保不需要已创建的图像。

第二。为图像的 src 使用了 data:URI 模式。

var s = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";

for (var i = 0; i < 100; i++){
    var img = document.createElement("img");
    img.src = s;
document.getElementById("myList1").appendChild(img);
setTimeout(function(){img = null;}, 1000);
}

在此处输入图像描述

这看起来很相似,虽然对我来说好一点,因为我在浏览器前观看并观察到使用的内存较少,垃圾收集几乎与上面相同。

第三。在代码中进行垃圾收集。

var s = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";

for (var i = 0; i < 100; i++){
    var img = document.createElement("img");
    img.src = "dot.png";  // or the other, both mean the same here.
    img.src = s;
document.getElementById("myList1").appendChild(img);
setTimeout(function(){img = null;}, 1000);
}

在此处输入图像描述

在这么短的测试时间内,我相信最后一种方法效果更好,因为它几乎可以立即释放空间,而无需等待进一步查看是否需要参考图像。

总而言之,当您绝对觉得必须释放某些东西时,您最好自己使用垃圾收集。

于 2014-01-01T11:34:17.723 回答
1

一个基本的图像池应该允许您回收 img 元素以供重复使用。由于您事先不知道总共有多少图像,因此只需根据需要扩展池大小即可。

像这样的东西应该工作:

    function getImg( id, src, alt ) {
        var pool = document.getElementById( 'image_pool' );
        var img = ( pool.children.length > 0 ) ? pool.removeChild( pool.children[0] ) : document.createElement( 'img' );
        img.id = id;
        img.src = src;
        img.alt = alt;
        return img;
    }
    function recycleImg( id ) {
        var img = document.getElementById( id );
        document.getElementById( 'image_pool' ).appendChild( img.parentNode.removeChild( img ) );
    }

在页面某处放置一个隐藏的“image_pool”容器,以在使用之间隐藏回收的图像:

<div id="image_pool" style="display:none;"></div>

然后任何时候你需要一个新的 img 元素,调用:

document.getElementById( 'some_element_id' ).appendChild( getImg( 'my_image_id', 'images/hello.gif', 'alt_text' ) );

当你完成它时:

recycleImg( 'my_image_id' );

jQuery 替代品

    function getImg( id, src, alt ) {
        var img;
        if( $("#image_pool").children().length > 0 ) {
            return $("#image_pool img:first-child").attr( { 'id': id, 'src': src, 'alt': alt } ).detach();
        }
        return $( "<img />'" ).attr( { 'id': id, 'src': src, 'alt': alt } );
    }
    function recycleImg( id ) {
        $( "#" + id ).detach().appendTo( $("#image_pool") );
    }

当你需要一个新的 img 元素时:

getImg( 'my_image_id', 'images/hello.gif', 'alt_text' ).appendTo( $( "#some_element_id" ) );

(回收工作同上)

于 2013-12-30T22:30:23.847 回答
0

尝试将 Javascript DOM 树对象设置为“null”。

首先,使用 chrome 开发者工具界面之类的东西,在 DOM 树层次结构中定位对象并检查它并找到包含图像二进制文件的对象。

尝试将该对象设置为 null,例如var obj = null;.

这应该告诉 Javascript 不再引用子对象并强制释放对象的内存。

于 2012-12-14T03:39:50.790 回答
0

设置为null至少是这里的解决方案。(火狐 69)

在一个项目中,我以 1 到 5 个批次加载图像以进行比较。图片平均 8-9MB。如果不将img元素设置为null移除后,RAM 的堆积会非常显着,并且会耗尽可用内存。

所以,从这个改变:

function clear (n) {
    while (n.lastChild) {
        n.removeChild(n.lastChild);
    return n;
};

对此:

function clear (n) {
    let x;
    while (n.lastChild) {
        x = n.removeChild(n.lastChild);
        x = null;
    }
    return n;
};

现在根本没有 RAM 积累。

于 2019-10-18T23:20:47.730 回答
-1

将图像设置为 div 的背景怎么样?我相信 Flickr 正在为他们的移动 html5 应用程序做类似的事情。

于 2012-12-31T05:48:01.633 回答