web-dev-qa-db-fra.com

Comment disposer des éléments DOM dans JavaScript afin d'éviter les fuites de mémoire

J'ai une application qui permet à un utilisateur de voir les détails sur un cas spécifique avec un message. Chaque fois qu'un utilisateur demande des données sur le serveur, je tire le balisage suivant.

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

Ensuite, je prends ce qui précède et innerhtml à un nouvel élément Dom comme si:

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

mais après ce qui précède, j'utilise un peu de jQuery pour enlever la méchante indemnité d'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);

Ma question est la suivante: lorsque vous utilisez iesieve Je remarque aucune fuite réelle mais un nombre croissant d'éléments DOM (donc de la mémoire).

Que puis-je améliorer au client de nettoyer ce désordre? NOTE - IE7/8 montrent ces résultats.

[~ # ~ ~] Edit [~ # ~] : J'ai enfin obtenu cela fonctionnant et décidé d'écrire un short Blog post avec code source complet.

28
Toran Billups

La partie délicate consiste à déterminer où une référence existe toujours aux nœuds incroyables.

Vous faites cela la solution difficile - vous ajoutez tout le marquage à la page, puis en supprimant les choses que vous ne voulez pas. Je le ferais de cette façon à la place:

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;

Ce n'est pas garanti d'arrêter la fuite, mais c'est un bon début.

12
savetheclocktower
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 = '';
}

source

7
David Driver

remove() et son ILK ne retirent que des éléments du DOM. Ils existent toujours en mémoire quelque part.

C'est un problème connu avec AJAX et Web 2.0. Il y a peu de choses que vous pouvez faire de côté de concevoir votre site pour vous assurer que vous avez occasionnellement une actualisation de la page pour essuyer les choses.

2
Randolpho

Je pense que la "consommation de mémoire toujours croissante" est quelque peu mal comprise. Cela concerne la gestion de la mémoire à l'intérieur du navigateur (ainsi que sur Windows en général) plus que cela n'a à voir avec votre code JS. Les gestionnaires de la mémoire continuent généralement d'attribuer (ou d'éviter de libérer) jusqu'à ce qu'ils soient. Sur les systèmes basés sur les pagesFiles et la cartographie de la mémoire, l'allocation et la libération de la mémoire sont très pratiques.

Donc, même si vos nœuds sont libérés de la structure de documents et de la DOM - il n'y a pratiquement aucun moyen de la mesurer de Windows elle-même dans "réeltime".

Essaye ça:

  1. Démarrez TaskManager, passez à l'onglet Processus et surveillez la mémoire de votre navigateur.

  2. Charge dans un document HTML qui alloue 100 000 nœuds, regardez la consommation de mémoire grandir

  3. Cliquez sur un bouton de la page qui libère tous les nœuds. Notez que peu arrive en termes de libération de la mémoire.

  4. Maintenant, minimisez la fenêtre du navigateur et maximisez-la à nouveau. Dans 90% de tous les cas, le navigateur décharge maintenant la mémoire si elle n'utilise pas et que vous verrez à quel point cela consomme-t-il vraiment.

Vous pouvez avoir un navigateur consommer de 500 mégaoctets de RAM (non mentionné ci-dessus), mais lorsque vous minimisez et maximisez-le, il libère tout et soudain, il n'utilise que 50 mégaoctets.

1