2009-04-20 27 views
27

我有一個應用程序允許用戶查看特定情況下的詳細信息,無需回傳。每次用戶向服務器請求數據時,我都會拉下以下標記。如何在JavaScript中處理DOM元素以避免內存泄漏

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

接下來,我走在上面,它的innerHTML到一個新的DOM元素,像這樣:

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

但是上面後,我用一些jQuery來去除討厭的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); 

我的問題是這樣的 - 當使用IESieve我注意到沒有實際的泄漏,但數量不斷增加的DOM元素(因此內存使用)。

我可以在客戶端改進什麼來實際清理這個混亂?注 - IE7/8都顯示了這些結果。

編輯:我終於得到這個工作,並決定寫一個短的blog post與完整的源代碼。

+0

你真的應該接受的答案,現在這個問題.... – Blazemonger 2011-11-04 13:27:26

+0

你能更新URL博客文章? – Christian 2014-04-08 08:53:45

+1

@Christian剛剛(對不起,鏈接斷了) – 2014-04-08 13:08:16

回答

12

棘手的部分是找出引用仍然存在的地方的有問題的節點。

你這樣做很難 - 你將所有的標記添加到頁面,然後刪除你不想要的東西。我會做這種方式來代替:

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; 

這並不能保證停止泄漏,但它是一個良好的開端。

2

remove()及其流行只從DOM中刪除元素。它們仍然存在於某個地方。

這是AJAX和Web 2.0的已知問題。除了設計網站之外,您幾乎無需做任何事情,以確保您偶爾會刷新頁面以消除丟失的內容。

1

我認爲「不斷增長的內存消耗」有些誤解。它必須處理瀏覽器內部的內存管理(以及一般的Windows),而不是與你的JS代碼相關。內存管理員通常會保持分配(或避免釋放),直到他們必須。在基於頁面文件和內存映射的系統上,分配和釋放內存非常耗時。因此,即使您的節點是從實際的文檔結構和DOM中釋放出來的,幾乎沒有任何方法可以從Windows自身的「實時」中進行衡量。

試試這個:

  1. 啓動任務管理器,切換到進程選項卡,看你的瀏覽器的內存分配100.000節點HTML文檔中

  2. 負載,看內存消耗增長

  3. 單擊釋放所有節點的頁面中的按鈕。注意,內存釋放方面很少發生。

  4. 現在最小化瀏覽器窗口,並再次最大化。在90%的情況下,瀏覽器現在會轉儲內存,如果不使用的話,你會看到它真的消耗了多少。

你可以有一個瀏覽器消耗RAM的500兆字節(以上未提及的例子),但是當你最小化和最大化,它釋放出的一切,突然間它僅使用50兆字節。

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