有一个known bug in webkit,当您从DOM中删除图像时,它不会释放与其关联的内存。
这是经常加载图像的单页应用程序的问题。
各种建议的解决方案是:
前三种方法对我不起作用。回收图像元素的主要缺点是,这意味着编写大量代码来进行管理。我正在通过AJAX加载可能包含图像的新HTML,因此我不一定知道将要加载的图像数量。
还有其他解决方法来解决此问题吗?
我使用了3种不同类型的方法...
First。确实添加了一组图像并将垃圾回收留给了浏览器。
肯定是垃圾收集,但是过一会儿,确保不需要创建的图像。
第二。对图像的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);
}
<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS9TTW1ldS5wbmcifQ==” alt =“在此处输入图像描述”>
这看起来很相似,虽然对我来说更好,因为我在浏览器前观看时发现使用的内存更少,并且垃圾回收与上面几乎相同。
第三。是否在代码中进行了垃圾回收。
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);
}
<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS9kNzNqUS5wbmcifQ==” alt =“在此处输入图像描述”>
在这么短的测试时间内,我相信最后一种方法效果更好,因为它几乎立即释放了空间,而无需等待是否进一步需要参考图像。
总而言之,当您绝对感觉必须释放某些东西时,最好自己使用垃圾回收。
基本图像池应允许您回收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" ) );
(回收工作与上述相同)
尝试将Javascript DOM树对象设置为“ null”。
[首先,使用chrome开发人员工具界面之类的东西,在DOM树层次结构中定位该对象,并对其进行检查,然后找到包含图像二进制文件的对象。
尝试将该对象设置为空,例如var obj = null;
。
这应该告诉Javascript子对象不再被引用,并强制释放对象的内存。
设置为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堆积。
将图像设置为div的背景呢?我相信Flickr正在为他们的移动html5应用执行类似操作。