0

每個ProcessingPayments()使用的內存增加。 CollectGarbage()沒有幫助。使用滴水查看內存使用情況,但不要查看任何DOM泄漏。IE JS內存泄漏,而XMLHTTP請求

我只使用IE8並在舊版本上測試。其他瀏覽器不感興趣。

如何在執行此腳本時減少增長的內存使用量?

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
    <html xmlns="http://www.w3.org/1999/xhtml"> 
    <head> 
     <title>JS IE XMLHTTP - Memory leaks</title> 
    </head> 

    <body onload="ProcessingPayments();locCollectGarbage();"> 

    <script language="JScript"> 
    var toProcessingPayments; 
    var ProcessingPaymentsPeriod = 1*60*1000; 
    var SessionCount = 1; 
    var CollectGarbageCount = 1; 


    function ProcessPayment(arrParams) { 
    var e; 
    var strURL = "http://www.facebook.com/"; 
    var strURLParam = ""; 
    try { var locHTTPRequest = new ActiveXObject("MSXML2.XMLHTTP.6.0"); } 
    catch (e) { var locHTTPRequest = new ActiveXObject("MSXML2.XMLHTTP"); } 

    function ProcessPaymentHTTPRequest() { 
     if (locHTTPRequest.readyState != 4) { 
     return; 
     } 

     if (locHTTPRequest.status != 200) { 
     document.getElementById("CurrentSession").innerHTML = document.getElementById("CurrentSession").innerHTML 
     +arrParams.i+" = error code "+locHTTPRequest.status+"<br />"; 

     return false; 
     } 

     if (locHTTPRequest.getResponseHeader("Content-Type").indexOf("text/html") < 0) { 
     document.getElementById("CurrentSession").innerHTML = document.getElementById("CurrentSession").innerHTML 
     +arrParams.i+" = wrong content type "+locHTTPRequest.getResponseHeader("Content-Type").indexOf("text/html")+"<br />"; 

     return false; 
     } 

     try { 
     document.getElementById("CurrentSession").innerHTML = document.getElementById("CurrentSession").innerHTML 
     +arrParams.i+" = processed<br />"; 

     return true; 

     } 
     catch(e) { 
     if (locHTTPRequest.responseXML.parseError != 0) { 
     return false; 
     } 
     else { 
     return false; 
     } 
     } 

     locHTTPRequest.abort(); 
     delete locHTTPRequest["onreadystatechange"]; 
     locHTTPRequest = null; 
    } // function ProcessPaymentHTTPRequest() 

    strURLParam = "?"+arrParams.i; 

    locHTTPRequest.open("get", strURL+strURLParam); 

    document.getElementById("CurrentSession").innerHTML = document.getElementById("CurrentSession").innerHTML 
     +arrParams.i+" = request<br />"; 

    locHTTPRequest.onreadystatechange = ProcessPaymentHTTPRequest; 

    locHTTPRequest.send(null); 
    } 


    function ProcessingPayments(arrPayment) { 
    var e; 

    toProcessingPayments = null; 

    document.getElementById("CurrentSession").innerHTML = ""; 

    for (var i = 0; i < 10; i++) { 
     ProcessPayment({ 
     i: i 
     }); 
    } 

    SessionCount++; 

    document.getElementById("Session").innerText = SessionCount; 

    toProcessingPayments = setTimeout(ProcessingPayments, ProcessingPaymentsPeriod); 
    } 


    function locCollectGarbage() { 
    CollectGarbage(); 

    document.getElementById("CollectGarbage").innerText = CollectGarbageCount; 

    CollectGarbageCount++; 

    setTimeout(locCollectGarbage, 5*60*1000); 
    } 
    </script> 
    </body> 

    <p>Sessions: <span id="Session">0</span></p> 
    <p>CollectGarbage(): <span id="CollectGarbage">0</span></p> 
    <hr /> 
    <br /> 

    <p>Current session:</p> 

    <p id="CurrentSession"></p> 

    </html> 
+0

您是否需要支持IE 6?如果沒有,爲什麼不使用本地'XMLHttpRequest'而不是使用ActiveX對象?也許這解決了你的問題。 – 2010-09-04 17:00:59

+0

2Mercel Korpel:我無法嘗試使用XMLHttpRequest,因爲我收到一條錯誤消息「訪問被拒絕」(跨域請求,因爲這個HTML基於本地計算機和URL位於facebook)。 所有設置,以防止這個錯誤,但內置XMLHttpRequest不起作用。 – plr 2010-09-04 19:45:45

回答

1
locHTTPRequest.onreadystatechange = ProcessPaymentHTTPRequest; 

創建本機的JScript對象(ProcessPaymentHTTPRequest函數,它有請求對象的範圍)和非JScript的對象(XMLHttpRequest ActiveX對象)之間的參考循環。正是這種參考迴路導致IE無法通過GC。

delete locHTTPRequest["onreadystatechange"]; 

雖然這將是一個本地JavaScript對象確定,在現實中delete不實際工作,從一個DOM對象中刪除的事件處理程序。所以處理程序和參考循環保持不變。相反,通常會使用Dud值(例如立即返回的預定義函數)或''null覆蓋locHTTPRequest.onreadystatechange處理程序。或者,使用addEventListener/attachEvent及其相應的移除處理程序方法。

CollectGarbage(); 

這是幹什麼的?從JS中影響GC的方法並不多。

旁白:

<script language="JScript"> 

type="text/javascript",而不是language。我知道你不關心非IE,但似乎毫無意義的不兼容以及非標準的點。

try { var locHTTPRequest = new ActiveXObject("MSXML2.XMLHTTP.6.0"); } 
catch (e) { var locHTTPRequest = new ActiveXObject("MSXML2.XMLHTTP"); } 

有沒有必要這樣做。您沒有使用新版MSXML版本的任何功能,因此只適用於未版本控制的XMLHttp。另外,首先去原生-JS XMLHttpRequest。不僅僅是因爲它存在於其他瀏覽器上,而且因爲它更高效,而且是原生JS,不會導致內存泄漏。

最佳:添加備用的IE6:

if (!window.XMLHttpRequest && 'ActiveXObject' in window) { 
    window.XMLHttpRequest= function() { 
     return new ActiveXObject('MSXML2.XMLHttp'); 
    } 
} 

,然後用標準的new XMLHttpRequest()無處不在。

locHTTPRequest.send(null); 

即使對於IE,這也是非標準的。如果您不想發送任何內容,請省略數據參數,而不是提供null

+0

我不能嘗試使用原生XMLHttpRequest,因爲我收到一條錯誤消息「訪問被拒絕」(跨域請求,因爲這個HTML基於本地計算機和URL位於facebook)。所有防止此錯誤的設置都是通過ActiveXH對象和XMLHttp跨域進行的,但內置XMLHttpRequest不起作用。 – plr 2010-09-04 19:55:55

+0

我改變代碼與您的建議: 1.更改刪除locHTTPRequest [「onreadystatechange」]; to locHTTPRequest.onreadystatechange = null; 2.禁用CollectGarbage(); 3.