2013-03-24 93 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