2009-04-20 14 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> 

次は、私はそうのような新しいDOM要素にそれ以上とinnerHTMLのを取る:

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

が、上記した後、私は厄介なの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); 
を削除するには、いくつかのjQueryを使用

私の質問はこれです - IESieveを使用すると、実際のリークはなく、ますます多くのDOM要素(メモリ使用量)が増えています。

この問題を実際に解決するためにクライアント側で改善できる点は何ですか?注 - 両方のIE7/8はこれらの結果を示します。

EDIT:私は最終的にこれを手に入れて、完全なソースコードで短いblog postを書き込むことに決めました。

+0

あなたは本当に今、この質問への答えを受け入れる必要があります.... – Blazemonger

+0

あなたはポストをブログにURLを更新することはできますか? – Christian

+1

@Christianちょうど(壊れたリンクのため申し訳ありません) –

答えて

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; 

これはリークを止めることはできませんが、それは良いスタートです。

+0

これは大きな前進です。なぜなら、ちょうどぶら下がっているDOM要素のほとんどが、私が削除して使用したことのない要素だからです。ありがとうございました! –

2

remove()およびそのilkは、DOMから要素を削除するだけです。彼らはまだどこかの記憶に存在しています。

これは、AJAXおよびWeb 2.0の既知の問題です。あなたのサイトを設計することから、ときどきページを更新して物事を拭き取ることができるようにすることはほとんどありません。

+3

あなたは、JavaScriptのガベージコレクタが回ってくるような方法でそれらを処分することはできません要素はメモリから削除されますか? –

+0

これは当てはまると思われますが、明らかにそうではありません。 – Randolpho

+2

ええと...掘り下げた後、このページで解説したソリューションのいくつかをお試しください:http://social.msdn.microsoft.com/Forums/en-US/iewebdevelopment/thread/c76967f0-dcf8-47d0-8984 -8fe1282a94f5 – Randolpho

1

「常に増加するメモリ消費」は多少誤解されていると思います。これは、JSコードと比べて、ブラウザ内のメモリ管理(一般的にはWindows上での処理)よりも重要です。メモリマネージャは、通常は、必要なときまで、割り当てを続ける(または解放しない)。ページファイルとメモリマッピングに基づくシステムでは、メモリの割り当てと解放は非常に時間がかかります。

ノードが実際の文書構造と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

+0

私はそれがゲームで少し遅れていることを知っています... –

+2

IEが吸いつく理由のそのような美しい例... –

+2

あなたはなぜこれが動作するかについての何の説明もしません。意味がない。 – vsync

関連する問題