2012-08-26 9 views
24

Mam łącza, które ładują strony do elementów iframe. Monitorowałem gromadzenie danych w pamięci za pomocą narzędzia do analizy pamięci w przeglądarce Google Chrome i zauważyłem pewne nieszczelności w pamięci.Elementy iframe i zarządzanie pamięcią w JavaScript

Załadowałem stronę i zrobiłem pierwszą migawkę, która dodała do 2.69 MB. Kliknąłem link otwierający stronę na element iframe i wykonałem kolejną migawkę, co daje mi łącznie 14.58 MB. Usunąłem iframe stosując następujący fragment: jquery

$('#myframe').unbind(); 
$('#myframe').remove(); 
/* 
* By the way, I also tried $('#myframe > *') as a selector. 
* It still didn't work. Even if it would, it doesn't look like a viable solution to me. 
* It looks too resource intensive. 
* 
* I forgot to mention that I am not using Ajax to load my pages 
*/ 

wziąłem kolejną migawkę i dostał 5.28 MB które wskazywały na odchylenie 2.59 MB od wartości początkowej, która według mojego rozumienia wskazuje wycieku pamięci.

Moje pytanie brzmi: czy po usunięciu elementu iframe (zawierającego załadowany dokument) czy moduł do zbierania śmieci nie uzna za konieczne usunięcia wszystkich obiektów zawartych w tym dokumencie z pamięci? Czy będę musiał to zrobić ręcznie?

Pomyślałem, że jeśli załaduję dokument do elementu iframe, jego rozmiar nie wpłynie na użycie pamięci na stronie nadrzędnej. Chociaż to będzie uważane za osobne okno, ale oczywiście nie było to dobre założenie z mojej strony.

Wszelkie sugestie, jak rozwiązać ten problem?

Dziękuję.

+1

Ten wątek wydaje się być dobrym punktem wyjścia dla tego problemu: http://stackoverflow.com/questions/3785258/how-to -remove-dom-elements-without-memory-leaks. – bperson

+0

Co dzieje się z pamięcią po wyładowaniu okna nadrzędnego? –

+1

Dzięki. Jeśli odświeżę okno nadrzędne, pamięć wróci do "2,69 MB" – Sthe

Odpowiedz

15

W elemencie iframe należy uruchomić przeładowanie przed usunięciem, a następnie usunąć.

<a href="#">Remove</a> 
<iframe src="url" />​ 

$('a').click(function(){ 
    $('iframe')[0].contentWindow.location.reload(); 
    setTimeout(function(){ 
     $('iframe').remove(); 
    }, 1000); 
});​ 

DEMO here.

Dodatkowo, możesz również wykonać ręczne czyszczenie - tzn. Jeśli masz dane w plikach cookie lub lokalnym pliku HTML5.

window.onbeforeunload = function(){ 
    $(document).unbind().die(); //remove listeners on document 
    $(document).find('*').unbind().die(); //remove listeners on all nodes 
    //clean up cookies 
    /remove items from localStorage 
} 
+0

Dziękuję Robin. Udało się :-) – Sthe

+0

Niestety nie udało się rozwiązać problemu z wyciekiem pamięci w przeglądarce iOS – andrewb

+1

Dzięki Robin, pierwsza opcja, którą udostępniasz, jest fantastyczna i zadziałała. Otwieram 8 elementów iframe, a ja zyskałem 20 MB i po ich zamknięciu i oczyszczeniu tak, jak wyjaśniłeś, mogłem odzyskać wszystkie 20 MB z powrotem. super Robin sir ... –

2

Jeśli jakiekolwiek obiekty z iframe odwołuje się do obiektu w oknie głównym, że obiekt nie zostanie usunięty z DOM, więc jeśli masz coś takiego:

głównym oknie:

var object = {}; 
function iframe_call(data){ 
    object.iframe_data = data.something 
} 

iframe:

function onClick(){ 
    parent_object.iframe_call(this); 
} 

to się dzieje, zwłaszcza jeśli odnoszą obiektów DOM.

+0

Dziękuję Cuzzea. Rozumiem twoją sprawę, ale na tym etapie nie wchodzę w interakcje z niczym w ramach elementu iframe. Właśnie ładowałem losowe strony. W tej chwili nie utworzyłem żadnego połączenia między oknem iframe i nadrzędnym. Poza tym usuwam element iframe wraz z jego zawartością. – Sthe

+0

możesz sprawdzić, co dokładnie zmieniło porównanie dwóch profili. Możesz zobaczyć winmerge'a, aby współczuć line by line. Nie zapomnij zamówić przez konstruktora, więc zamówienie jest takie samo – cuzzea

0
var frame = document.getElementById("myframe"); 
frame.src = "about:blank"; 

To działało ode mnie i uniemożliwił wycieków pamięci. Ig musisz zniszczyć rodzica ramki iframe, zrób to z pewnym opóźnieniem, aby zapobiec wyciekom pamięci