2013-03-24 3 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 />を使用する場合に何が起こるか見ることにしました。

だから私のコードは現在のフレームが作成されていることですが、できるだけ早くIMAGEURLの変更など、フレームは単に更新し、追加のリソースを作成していない今、何が起こる

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

のように見えます。

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

+0

私はすでにイメージを削除してから新しいイメージを追加しようとしましたが、イメージリソースは常に蓄積されています。例についてはこのフィドルを参照してください。 http://jsfiddle.net/ezb9e/ –

+0

データを更新するときに画像URLが常に変更されていますか、それとも比較的一定のままですか? –

答えて

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のように、イメージの作成に関してかなりのメモリリークがあります。提案された解決策(これは、一部の人にのみ有効)は、アドバンストインターネットオプションで* Enable SmartScreen Filterを有効にすることです。あなたは本当にIE8のサポートが必要で、iframeを使いたくない場合は、かなり残念な回避策ですが、価値があるかもしれません。出典:http://com.hemiola.com/2009/11/23/memory-leaks-in-ie8/#comment-880 – snickle

関連する問題