2009-04-20 16 views
27

Ho un'applicazione che consente a un utente di visualizzare i dettagli su un caso specifico senza un postback. Ogni volta che un utente richiede dati dal server, tiro giù il seguente markup.Come eliminare elementi DOM in JavaScript per evitare perdite di memoria

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

successivo prendo quanto sopra e InnerHtml a un nuovo elemento DOM in questo modo:

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

ma dopo quanto sopra, io uso un po 'di jQuery per rimuovere il brutto aspnet spazzatura

$('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); 

La mia domanda è questa: quando si utilizza IESieve non noto perdite effettive ma un numero sempre crescente di elementi DOM (quindi utilizzo della memoria).

Cosa posso migliorare nel lato client per pulire effettivamente questo pasticcio? Nota: entrambi IE7/8 mostrano questi risultati.

EDIT: Ho finalmente ottenuto questo funzionamento e ho deciso di scrivere un breve blog post con il codice sorgente completo.

+0

Si dovrebbe davvero accettare una risposta a questa domanda ora .... – Blazemonger

+0

Puoi aggiornare URL a blog post? – Christian

+1

@Christian ha appena fatto (mi dispiace per il collegamento interrotto) –

risposta

12

La parte difficile è capire dove esiste ancora un riferimento ai nodi incriminati.

Lo stai facendo nel modo più duro: aggiungi tutti i markup alla pagina, quindi rimuovi le cose che non vuoi. Lo farei invece in questo modo:

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; 

Questo non è garantito per fermare la perdita, ma è un buon inizio.

+0

Questo è un grande passo avanti perché la maggior parte degli elementi DOM che sono rimasti in giro sono quelli che stavo rimuovendo e mai usato. Grazie! –

2

remove() e il suo elenco rimuove solo elementi dal DOM. Esistono ancora nella memoria da qualche parte.

Questo è un problema noto con AJAX e Web 2.0. C'è poco che puoi fare oltre a progettare il tuo sito per assicurarti di avere occasionalmente un aggiornamento della pagina per cancellare le cose.

+3

Non è possibile disporre di questi in modo tale che quando il garbage collector di javascript viene in giro, questi gli elementi vengono rimossi dalla memoria? –

+0

Si potrebbe presumere che sia così, ma a quanto pare non lo è. – Randolpho

+2

Hmm ... dopo alcuni scavi, potresti provare alcune delle soluzioni discusse in questa pagina: http://social.msdn.microsoft.com/Forums/en-US/iewebdevelopment/thread/c76967f0-dcf8-47d0-8984 -8fe1282a94f5 – Randolpho

1

Penso che "il crescente consumo di memoria" sia in qualche modo frainteso. Ha a che fare con la gestione della memoria all'interno del browser (e anche su Windows in generale) più di quanto abbia a che fare con il tuo codice JS. I gestori di memoria in genere continuano a allocare (o evitare di rilasciare) fino a quando non devono farlo. Sui sistemi basati su file di paging e sulla mappatura della memoria, allocare e rilasciare la memoria richiede molto tempo.

Quindi, anche se i nodi vengono rilasciati dalla struttura del documento e dal DOM effettivo, non c'è quasi alcun modo per misurarlo da Windows stesso in "realtime".

Prova questo:

  1. Inizio Taskmanager, passare alla scheda Processo e guardare la memoria del browser

  2. carico in un documento HTML che alloca 100.000 nodi, guardare il consumo di memoria crescere

  3. Fare clic su un pulsante nella pagina che rilascia tutti i nodi. Si noti che poco succede in termini di rilascio di memoria.

  4. Ora riduci a icona la finestra del browser e ingrandiscila di nuovo.Nel 90% dei casi il browser scarica la memoria se non la usa e vedrai quanto consuma davvero.

si può avere un navigatore consumano 500 megabyte di RAM (non suddetta esempio), ma quando si minimizza e massimizzare esso, rilascia tutto e all'improvviso utilizza solo 50 megabyte.

6
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

+0

So che è un po 'in ritardo nel gioco ... –

+2

Un bell'esempio del motivo per cui IE fa schifo ... –

+2

non si spiega perché dovrebbe funzionare anche così. non ha senso. – vsync

Problemi correlati