2013-03-24 4 views
14

Ich habe eine Webanwendung, die dynamisch Daten über einen langen Zeitraum lädt. Innerhalb der Daten befinden sich Links zu Bildern, die dann im Browser gerendert werden.Richtig entsorgen von Browserressourcen

z.B.

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

Ich verwende Knockoutjs ‚s Vorlage, um die Daten auf dem Bildschirm machen verbindlich.

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

Also jedes Mal, wenn die Objektänderungen über einen Ajax-Aufruf, die Knockoutjs Vorlage mit den Daten neu gerendert wird, und die Bilder ändern.

Nach einer langen Zeit bauen sich diese Bilder auf und werden mehr Speicher verbrauchen. Moderne Browser scheinen besser zu bewältigen, aber das Problem ist hauptsächlich mit IE8 (wir unterstützen < IE8 nicht). Selbst in modernen Browsern wird der Speicher irgendwann so hoch, dass der Browser einfriert.

In diesem Screenshot sehen Sie ein Beispiel für den Aufbau der Bildressourcen.

enter image description here

entschied ich mich, um zu sehen, was passieren würde, wenn stattdessen einen <img /> Tag der Verwendung ein <iframe /> verwenden.

So jetzt mein Code sieht aus wie

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

Was jetzt passiert, ist, dass der Rahmen geschaffen wird, aber sobald die imageUrl ändert, wird der Rahmen einfach Updates und schafft keine zusätzlichen Mittel.

enter image description here

enter image description here

Also, wenn ich unten die Browser Speichernutzung halten will, kann ich diese <iframe /> Technik verwenden, aber ich mag es nicht. Es zwingt mich, viele andere Änderungen an der Anwendung vorzunehmen, und ich muss iframes verwenden!

Ich habe jetzt verschiedene Tests durchgeführt, um zu sehen, wie viel Speicher mit beiden Techniken verbraucht wird, und im gleichen Zeitraum steigt der Speicher von 81.000.000 auf 200.000.000 (mit <img />) im Vergleich zu 81.000.000 auf 98.000.000 (mit <iframe />)

Frage

gibt es eine bessere Art und Weise Bildressourcen in einem Browser zu verwalten? Gibt es eine Möglichkeit, dieses Bild richtig zu entsorgen? Ich habe das Internet nach einer Antwort gesucht, aber bis jetzt habe ich nichts gefunden.

bearbeiten

Auf der sehr einfachen Ebene. Ich habe versucht, ein Bild über die jQuery-Methode remove() zu entfernen, aber die Bildressource wird nie entfernt. Sehen Sie diese Geige für ein sehr einfaches Beispiel.http://jsfiddle.net/ezb9e/

Code:

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

Ist es möglich, diese Hooks zu verwenden: http://knockoutjs.com/documentation/template-binding.html#note_3_using_afterrender_afteradd_and_beforeremove, um das Bild manuell aus dem DOM zu entfernen, bevor das neue hinzugefügt wird? Das sollte das Problem stoppen. – Nik

+0

Ich habe bereits versucht, das Bild zuerst zu entfernen und dann ein neues hinzuzufügen, aber die Bildressourcen werden immer aufgebaut. Sehen Sie diese Geige für ein Beispiel. http://jsfiddle.net/ezb9e/ –

+0

Ändern sich die Bild-URLs immer, wenn Sie die Daten aktualisieren, oder bleiben sie relativ konstant? –

Antwort

5

Ich würde versuchen, eine benutzerdefinierte Bindung verwenden, und erstellen und die Bilder in das zerstören. Ich hatte letztes Jahr ein ähnliches Problem mit einer SVG, und das musste ich tun.

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; 
    } 
}; 

Hier ist Ihr ursprüngliches Problem neu zu erstellen:

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

Und hier ist meine Version:

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

Speicher gehen zunächst, aber es Müll hin gesammelt wird und wieder , damit es nie außer Kontrolle gerät. Dies wird in IE9 und Chrome getestet.

Update Hmmm, ich bin jetzt nicht davon überzeugt, dass dies das Problem in IE8 vollständig behebt. Ich habe die Geige in sIEve laufen lassen, und die Speicherkapazität steigt immer noch, obwohl SIEve Hooks in DOM-Knoten hinzufügt, könnte es ein Ergebnis davon sein, es in SIEVE auszuführen. Chrome ist definitiv in Ordnung, und IE9 scheint zumindest viel besser zu sein, wenn nicht vollständig behoben.

+0

Leider sieht es aus wie IE8 hat nur ein ziemlich schlechtes Speicherleck in Bezug auf die Erstellung von Bildern. Eine vorgeschlagene Lösung (die nur für einige Leute zu funktionieren scheint), ist das Aktivieren von "SmartScreen-Filter aktivieren" in den erweiterten Internetoptionen. Ziemlich die schreckliche Problemumgehung, aber möglicherweise lohnt es sich, wenn Sie wirklich die IE8-Unterstützung benötigen und keine Iframes verwenden möchten. Quelle: http://com.hemiola.com/2009/11/23/memory-leaks-in-ie-8/#comment-880 – snickle