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 未満はサポートしていません)。最新のブラウザでも、最終的にはメモリが非常に高くなり、ブラウザがフリーズします。

イメージ リソースの構築例については、このスクリーン ショットを参照してください。

ここに画像の説明を入力

<img />タグを使用する代わりに を使用するとどうなるかを確認することにしました<iframe />

だから私のコードは今のようになります

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

ここでフレームが作成されますが、imageUrl が変更されるとすぐに、フレームは単純に更新され、追加のリソースは作成されません。

ここに画像の説明を入力

ここに画像の説明を入力

したがって、ブラウザのメモリ使用量を抑えたい場合は、この<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);    
});
4

1 に答える 1

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 は、完全に修正されていないとしても、少なくともはるかに優れているようです。

于 2013-03-25T10:43:28.563 に答える