2008-11-09 10 views
7

Ich arbeite an einer Webanwendung, die entwickelt wurde, um eine Reihe von Daten anzuzeigen, die regelmäßig mit AJAX aktualisiert werden. Das allgemeine Benutzungsszenario wäre, dass ein Benutzer es den ganzen Tag offen lässt und ab und zu einen Blick darauf wirft.Verhindern von AJAX-Speicherlecks

Ich stoße auf ein Problem, bei dem der Speicherbedarf des Browsers im Laufe der Zeit langsam zunimmt. Dies geschieht sowohl in Firefox als auch in IE 7 (obwohl nicht in Chrome). Nach ein paar Stunden kann IE7 eine Grundfläche von ~ 200 MB und FF3 eine Grundfläche von ~ 400 MB haben.

Nach vielen Tests habe ich festgestellt, dass der Speicherverlust nur auftritt, wenn die AJAX-Anrufe beantwortet werden. Wenn der Server auf nichts reagiert, kann ich die Seite stundenlang geöffnet lassen und der Footprint wird nicht wachsen.

Ich verwende einen Prototyp für meine AJAX-Anrufe. Also, ich vermute, es gibt ein Problem mit dem OnSuccess Callback, der diese Speicherlecks erzeugt.

Hat jemand irgendwelche Tipps zur Verhinderung von Speicherlecks mit Prototyp/AJAX? Oder irgendwelche Methoden zur Problembehandlung?

EDIT: herausgefunden, das Problem liegt in einer js-Grafik-Bibliothek, die ich verwende. Kann gesehen werden here.

Antwort

10

Die größte Sache, auf die Sie achten können, ist Ereignisse und wie Sie sie zuweisen.

Nehmen Sie zum Beispiel dieses Szenario (da Sie nicht ein zur Verfügung gestellt haben):

<div id="ajaxResponseTarget"> 
    ... 
</div> 
<script type="text/javascript"> 
    $(someButton).observe('click', function() { 
     new Ajax.Updater($('ajaxResponseTarget'), someUrl, { 
      onSuccess: function() { 
       $$('#ajaxResponseTarget .someButtonClass').invoke('observe', 'click', function() { 
        ... 
       }); 
      } 
     }); 
    }); 
</script> 

Dies wird ein Speicherleck schaffen, denn wenn #ajaxResponseTarget aktualisiert (intern wird Prototype innerHTML verwendet) Elemente mit click Ereignisse werden aus dem Dokument entfernt, ohne dass ihre Ereignisse entfernt werden. Wenn Sie das zweite Mal auf someButton klicken, haben Sie dann doppelt so viele Ereignisbehandlungsroutinen, und die Speicherbereinigung kann die erste Gruppe nicht entfernen.

Ein Weg, dies zu vermeiden, ist Ereignis Delegation zu verwenden:

<div id="ajaxResponseTarget"> 
    ... 
</div> 
<script type="text/javascript"> 
    $('ajaxResponseTarget').observe('click', function(e) { 
     if(e.element().match('.someButtonClass')) { 
      ... 
     } 
    }); 
    $(someButton).observe('click', function() { 
     new Ajax.Updater($('ajaxResponseTarget'), someUrl); 
    }); 
</script> 

Aufgrund der Art und Weise DOM-Ereignisse arbeiten, um zu bestimmen, die „Klick“ auf .someButtonClass wird Feuer auch auf #ajaxResponseTarget und Prototype macht es einfach tot Welches Element war das Ziel der Veranstaltung? Den Elementen innerhalb von sind keine Ereignisse zugewiesen, daher ist es nicht möglich, den Inhalt durch verwaiste Ereignisse von Zielen zu ersetzen.

+0

+1 Gute Informationen, obwohl ich nach dem ersten Laden der Seite nie neue Ereignisse erstelle. Immer noch versuchen herauszufinden, was ich mache, würde das Problem verursachen. –

+1

Wenn Sie keine Ereignisse erstellen ... Warum haben Sie das als Ihre Antwort akzeptiert? – Sean

-3

Ich kann falsch liegen, aber es klingt wie Sie Schließungen um das Antwortobjekt erstellen. Jedes Antwortobjekt wird anders sein, was zu einem erhöhten Speicherbedarf führt.

+0

Können Sie etwas erklären? Entschuldigung, ich bin mir nicht sicher, was Sie mit "Verschlüsse um das Antwortobjekt" meinen. Meinst du eine Funktion? –

+0

http://en.wikipedia.org/wiki/Closure_(computer_science) –