开发者

Memory leaks in IE JS while XMLHTTP requests

开发者 https://www.devze.com 2023-01-14 16:35 出处:网络
Each ProcessingPayments() used memory increase. CollectGarbage() not helps. Use Drip to view memory usage, but don\'t view any DOM leaks.

Each ProcessingPayments() used memory increase. CollectGarbage() not helps. Use Drip to view memory usage, but don't view any DOM leaks.

I use only IE8 and tested on older versions. Other browsers not interested.

How can I decrease growing memory usage while execute this script?

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


locHTTPRequest.onreadystatechange = ProcessPaymentHTTPRequest;

Creates a reference loop between a native-JScript object (the ProcessPaymentHTTPRequest function, which has the request object in scope) and a non-JScript object (the XMLHttpRequest ActiveX object). It is this kind of reference loop that makes IE fail to GC.

delete locHTTPRequest["onreadystatechange"];

Whilst that would be OK for a native JavaScript object, in reality delete doesn't actually work to remove an event handler from a DOM object. So the handler and reference loop remains in place. What is typically done instead is to overwrite the locHTTPRequest.onreadystatechange handler with a dud value, such as a predefined function that immediately returns, or '', or null. Or alternatively, use addEventListener/attachEvent and their corresponding remove-handler methods.

CollectGarbage();

What does that do? There's not really much you can do to influence GC from JS.

Aside:

<script language="JScript">

type="text/javascript" instead of language. I know you don't care about non-IE, but there seems little point in being gratuitous incompatible as well as non-standard.

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

There is no need to do this. You aren't using any features of the newer MSXML version, so just plump for unversioned XMLHttp. Also, go for native-JS XMLHttpRequest first. Not just because it exists on other browsers, but also because it's more efficient and, being native JS, doesn't cause memory leaks.

Best: add fallback for IE6:

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

and then just use standard new XMLHttpRequest() everywhere.

locHTTPRequest.send(null);

This is non-standard even for IE. Omit the data argument if you don't want to send anything, rather than supplying null.

0

精彩评论

暂无评论...
验证码 换一张
取 消