0

Chaque traitement ProcessingPayments() a utilisé une augmentation de la mémoire. CollectGarbage() n'aide pas. Utilisez Drip pour afficher l'utilisation de la mémoire, mais ne pas afficher les fuites DOM. Je n'utilise que IE8 et testé sur des versions plus anciennes. Les autres navigateurs ne sont pas intéressés.La mémoire fuit dans IE JS pendant les requêtes XMLHTTP

Comment puis-je diminuer l'utilisation croissante de la mémoire pendant l'exécution de ce 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> 
+0

Devez-vous également prendre en charge IE 6? Si non, pourquoi ne pas utiliser 'XMLHttpRequest' natif au lieu d'utiliser des objets ActiveX? Peut-être que cela résout votre problème. –

+0

2Mercel Korpel: Je ne peux pas essayer d'utiliser XMLHttpRequest, parce que j'obtiens un message d'erreur "accès refusé" (requête interdomaine, car ce code HTML est basé sur l'ordinateur local et l'URL située sur facebook). Tous les paramètres pour éviter cette erreur ont été créés, mais avec XMLHttpRequest intégré ne fonctionne pas. – plr

Répondre

1
locHTTPRequest.onreadystatechange = ProcessPaymentHTTPRequest; 

crée une boucle de référence entre un objet natif JScript (la fonction ProcessPaymentHTTPRequest, qui a pour objet de requête de portée) et d'un objet non JScript (l'objet ActiveX XMLHttpRequest). C'est ce type de boucle de référence qui fait échouer IE à GC.

delete locHTTPRequest["onreadystatechange"]; 

Alors que ce serait OK pour un objet JavaScript natif, en réalité delete ne fonctionne pas vraiment pour supprimer un gestionnaire d'événements à partir d'un objet DOM. Le gestionnaire et la boucle de référence restent donc en place. Ce qui est généralement effectué à la place est d'écraser le gestionnaire locHTTPRequest.onreadystatechange avec une valeur ratée, telle qu'une fonction prédéfinie qui renvoie immédiatement, ou '' ou null. Ou bien, utilisez addEventListener/attachEvent et les méthodes remove-handler correspondantes.

CollectGarbage(); 

Qu'est-ce que cela fait? Il n'y a pas vraiment grand-chose que vous puissiez faire pour influencer GC de JS.

En plus:

<script language="JScript"> 

type="text/javascript" au lieu de language. Je sais que vous ne vous souciez pas de non-IE, mais il semble peu utile d'être gratuit et incompatible non standard.

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

Il n'est pas nécessaire de le faire. Vous n'utilisez aucune des fonctionnalités de la version MSXML plus récente, il suffit donc de dodu pour XMLHttp non versionnée. En outre, optez pour natif-JS XMLHttpRequest en premier. Non seulement parce qu'il existe sur d'autres navigateurs, mais aussi parce qu'il est plus efficace et, étant JS natif, ne provoque pas de fuites de mémoire.

meilleur: ajouter fallback pour IE6:

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

puis il suffit d'utiliser la norme new XMLHttpRequest() partout.

locHTTPRequest.send(null); 

Ceci est non standard même pour IE. Omettez l'argument de données si vous ne voulez rien envoyer, plutôt que de fournir null.

+0

Je ne peux pas essayer d'utiliser XMLHttpRequest natif, parce que j'obtiens un message d'erreur "accès refusé" (requête interdomaine, car ce code HTML est basé sur l'ordinateur local et l'URL située sur facebook).Tous les paramètres pour éviter cette erreur ont été faites et avec l'objet activex XMLHttp fonctionne sur le domaine croisé, mais avec XMLHttpRequest intégré ne fonctionne pas. – plr

+0

Je change le code avec vos suggestions: 1. change delete locHTTPRequest ["onreadystatechange"]; à locHTTPRequest.onreadystatechange = null; 2. Désactivez CollectGarbage(); 3.

Questions connexes