有一个known bug in webkit,当您从DOM中删除图像时,它不会释放与之关联的内存。
这是单页应用经常加载图片的问题。
各种建议的解决方案是:
前三种方法对我不起作用。回收图像元素的主要缺点是它意味着编写大量代码来管理它。我正在通过AJAX加载可能包含图像的新HTML,因此我不一定知道要加载的图像数量。
还有其他解决方法可以解决这个问题吗?
答案 0 :(得分:12)
我使用了3种不同类型的方法......
<强>第一即可。添加了一组图像并将垃圾收集留给了浏览器。
它肯定是垃圾收集,但过了一会儿,确保不需要已经创建的图像。
<强>第二即可。使用了数据:图像的src的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);
}
在这短暂的测试时间里,我相信最后一种方法效果更好,因为它几乎可以立即释放空间,而无需等待进一步查看引用图像是否需要。
总而言之,当您绝对觉得必须释放某些东西时,最好自己使用垃圾收集。
答案 1 :(得分: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" ) );
(回收与上述相同)
答案 2 :(得分:0)
尝试将Javascript DOM树对象设置为“null”。
首先,使用chrome开发人员工具界面之类的东西,在DOM树层次结构中找到对象并检查它,然后找到包含图像二进制文件的对象。
尝试将该对象设置为null,例如var obj = null;
。
这应该告诉Javascript不再引用子项并强制释放对象的内存。
答案 3 :(得分:0)
设置为null
至少是这里的解决方案。 (Firefox 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。
答案 4 :(得分:-1)
如何将图像设置为div的背景?我相信Flickr正在为他们的移动html5应用程序做这样的事情。