Jak pozbyć się elementów DOM w JavaScript, aby uniknąć wycieków pamięci

Mam aplikację, która pozwala użytkownikowi przeglądać szczegóły dotyczące konkretnego przypadku z / out postback. Za każdym razem, gdy użytkownik żąda danych z serwera, ściągam następujące znaczniki.

<form name="frmAJAX" method="post" action="Default.aspx?id=123456" id="frmAJAX">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" />
</div>
<div>
<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" />
</div>
<div id="inner">
<!-- valid info here --!>
</div>
</form>

Następnie biorę powyższe i innerHTML to do nowego elementu DOM jak tak:

   success: function(xhtml) {
        var tr = document.createElement('tr');
        var td = document.createElement('td');
        var container = document.createElement('div');

        obj.parentNode.parentNode.parentNode.insertBefore(tr, obj.parentNode.parentNode.nextSibling);

        td.appendChild(container);
        container.innerHTML = xhtml;
        tr.appendChild(td);

Ale po powyższym używam jQuery, aby usunąć paskudne śmieci aspnet

$('form:eq(1)').children().each(
    function() {
        if ($('form:eq(1)').find('div').filter(function() { return $(this).attr('id') == ''; }).remove());
    }
);

//Capture the remaining children
var children = $('form:eq(1)').children();

// Remove the form
$('form:eq(1)').remove();

// append the correct child element back to the DOM
parentObj.append(children);

Moje pytanie Jest Takie - podczas korzystania z IESieve nie zauważam żadnych przecieków, ale stale rosnąca liczba DOM elementów (a więc wykorzystanie pamięci).

Co mogę poprawić po stronie klienta, aby faktycznie posprzątać ten bałagan? Uwaga - oba IE7 / 8 pokazują te wyniki.

EDIT: W końcu udało mi się to uruchomić i postanowiłem napisać krótki blog post z pełnym kodem źródłowym.

Author: Toran Billups, 2009-04-20

4 answers

Najtrudniejszą częścią jest ustalenie, gdzie nadal istnieje odniesienie do obrażających węzłów.

Robisz to w trudny sposób-dodajesz wszystkie znaczniki na stronie, a następnie usuwasz rzeczy, których nie chcesz. Zrobiłbym to tak zamiast:

var div = document.createElement('div');
// (Don't append it to the document.)

$(div).html(xhtml);

var stuffToKeep = $(div).find("form:eq(1)> *").filter(
  function() {
    return $(this).attr('id') !== '';
  }
);

parentObj.append(stuffToKeep);

// Then null out the original reference to the DIV to be safe.
div = null;
To nie jest gwarantowane, aby zatrzymać wyciek, ale to dobry początek.
 12
Author: savetheclocktower,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-20 15:50:19
function discardElement(element) {
    var garbageBin = document.getElementById('IELeakGarbageBin');
    if (!garbageBin) {
        garbageBin = document.createElement('DIV');
        garbageBin.id = 'IELeakGarbageBin';
        garbageBin.style.display = 'none';
        document.body.appendChild(garbageBin);
    }
    // move the element to the garbage bin 
    garbageBin.appendChild(element);
    garbageBin.innerHTML = '';
}

Źródło

 6
Author: David Driver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-04 10:39:24

remove() a jego ilk usuwa tylko elementy z DOM. Gdzieś w pamięci wciąż istnieją.

Jest to znany problem z AJAX i Web 2.0. Niewiele możesz zrobić, oprócz projektowania witryny, aby zapewnić, że od czasu do czasu odświeżasz stronę, aby usunąć rzeczy.

 2
Author: Randolpho,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-20 15:02:47

Myślę ,że "zawsze rosnące zużycie pamięci" jest nieco źle zrozumiane. Ma to związek z zarządzaniem pamięcią w przeglądarce (a także ogólnie w systemie Windows) bardziej niż z kodem JS. Menedżerowie pamięci zazwyczaj przydzielają (lub unikają zwalniania), dopóki nie będą musieli. W systemach opartych na plikach stron i mapowaniu pamięci przydzielanie i zwalnianie pamięci jest bardzo czasochłonne.

Więc nawet jeśli twoje węzły są zwolnione z rzeczywistej struktury dokumentu i DOM-tam trudno jest zmierzyć go z samego systemu Windows w "czasie rzeczywistym".

Spróbuj tego:

  1. Uruchom Taskmanager, przejdź do zakładki proces i obserwuj pamięć przeglądarki

  2. Wczytaj dokument HTML, który przydziela 100.000 węzłów, obserwuj wzrost zużycia pamięci

  3. Kliknij przycisk na stronie, który zwalnia wszystkie węzły. Zauważ, że niewiele się dzieje pod względem uwalniania pamięci.

  4. Teraz zminimalizuj okno przeglądarki i zmaksymalizuj je jeszcze raz. W 90% wszystkich przypadków przeglądarka zrzuca teraz pamięć, jeśli nie używa, a zobaczysz, ile naprawdę zużywa.

Możesz mieć przeglądarkę zużywać 500 megabajtów pamięci ram( nie wyżej wymieniony przykład), ale gdy ją zminimalizujesz i zmaksymalizujesz, zwalnia wszystko i nagle używa tylko 50 megabajtów.

 1
Author: Jon Lennart Aasenden,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-21 12:42:15