2013-03-24 186 views
14

我有一个Web应用程序,它可以在很长一段时间内动态加载数据。在数据中有指向图像的链接,然后在浏览器中呈现图像。正确处理浏览器资源

例如

var object = { 
    Name: ko.observable("Foo"), 
    Ref: ko.observable("Bar"), 
    ImageUrl: ko.observable("http://.....")   
} 

我正在使用Knockoutjs的模板绑定来在屏幕上呈现数据。

<img data-bind="attr: { src: imageUrl }" />   

因此,每当对象通过Ajax调用进行更改时,Knockoutjs模板都会与数据一起重新渲染,并且图像会更改。

经过很长一段时间后,这些图像会累积起来,并会消耗更多的记忆。现代浏览器似乎应付得更好,但问题主要在于IE8(我们不支持IE8的<)。即使在现代浏览器中,内存最终会变得如此之高以至于浏览器死机。

查看此屏幕截图,查看构建图像资源的示例。

enter image description here

我决定去看看会发生什么,如果不是使用<img />标签,使用<iframe />

所以我的代码现在看起来像

<iframe data-bind="attr: { src: imageUrl }"></iframe> 

现在会发生什么是框架被创建,但只要IMAGEURL变化框架简单地更新,并且不产生额外的资源。

enter image description here

enter image description here

所以,如果我想保持浏览器的内存使用情况下,我可以用这个<iframe />技术,但我不喜欢它。它迫使我对应用程序进行其他更改,另外我需要使用iframe!

我已经运行了各种测试,看看有多少内存用完了这两种技术,并且在同一段时间内存将从81,000k增加到200,000k(与<img />)相比,81,000k到98,000k (与<iframe />

问题

有没有更好的方式来在浏览器中管理图像资源?有没有办法正确处理这个图像? 我已经在网上搜索了答案,但到目前为止我还没有找到任何答案。

编辑

在最基层。我试图通过jQuery方法remove()删除图像,但图像资源永远不会被删除。看这个小提琴是一个非常基本的例子。http://jsfiddle.net/ezb9e/

代码:

HTML

<img src="http://www.fillmurray.com/200/300" /> 

JS

$(function(){ 
    setTimeout(function(){ 
     $('img').remove(); 
     $('body').append($('<img />', { attr: { src: 'http://www.fillmurray.com/300/200' }})); 
    }, 3000);  
}); 
+0

可能有可能使用这些挂钩:http://knockoutjs.com/documentation/template-binding.html#note_3_using_afterrender_afteradd_and_beforeremove在手动添加新建之前自己从DOM中删除图像?这应该能够解决问题。 – Nik 2013-03-24 11:07:50

+0

我已经尝试先删除图像,然后添加一个新的图像,但图像资源始终建立。以此小提琴为例。 http://jsfiddle.net/ezb9e/ – 2013-03-24 11:18:35

+0

刷新数据时图像URL是否总是在变化,还是保持相对稳定? – 2013-03-24 17:37:25

回答

5

我会尝试使用自定义绑定,以及创建和销毁的图像。去年我与SVG有类似的问题,这就是我必须做的。

ko.bindingHandlers.createImage = { 
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
    // Use something unique to identify this image object 
    var imageName = viewModel.Name(); 
    var parent = bindingContext.$parent; 

    var imageObject = parent.Images[imageName]; 

    if (imageObject) { 
     $(element).empty() 
     imageObject = null; 
    } 

    imageObject = $(element).append('<img src="' + viewModel.imgSrc() + '" />')[0]; 
    parent.Images[imageName] = imageObject; 
    } 
}; 

这里的重新建立原始的问题:

http://jsfiddle.net/manzanotti/ezb9e/5/

这是我的版本:

http://jsfiddle.net/manzanotti/ezb9e/13/

记忆开始上升,但它可以让垃圾收集时不时,所以它永远不会失控。这在IE9和Chrome中进行了测试。

更新嗯,我现在不相信这完全解决了IE8中的问题。我已经在sIEve中运行了小提琴,并且内存仍在增加,尽管由于sIEve在DOM节点中添加了钩子,它可能是在sIEve中运行它的结果。尽管Chrome确实很好,但IE9似乎至少要好得多,如果不是完全固定的话。

+0

不幸的是,它看起来像IE8只是在图像创建方面有一个非常糟糕的内存泄漏。建议的解决方案(似乎只适用于某些人)应在高级Internet选项中打开*“启用SmartScreen筛选器”。相当糟糕的解决方法,但如果您确实需要IE8支持并且不想使用iframe,则可能值得。资料来源:http://com.hemiola.com/2009/11/23/memory-leaks-in-ie8/#comment-880 – snickle 2014-07-23 20:59:51