Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to clean up JSONP memory in Internet Exploreor

I am new to JSONP development and I find out that IE 7/8 will not clean up the memory of which JSONP script takes. This leads to very high memory consumption in my page after running a couple of hours.

I looked around the Internet and found most of the fixes are based on the tip from Neil Fraser. From the blog it is said that you need to delete all the properties in the script by using code like

    var tmp;
    while (tmp = document.getElementById('JSONP')) {
        tmp.parentNode.removeChild(tmp);

        // this deletion will create error in IE.
        for (var prop in tmp) delete tmp[prop];
        tmp = null;
    }

Unfortunately the deletion will create error of "Object does not support this action" in IE and it will not free the memory.

So my question is how to really free the memory of my JSONP script?

I put my testing code as below:

Testing.html

<html><head></head><body><script>
var script,
head = document.getElementsByTagName('head')[0],
loadCount= 0,
uuid= 1,
URL= "memleaktest.js?uuid=",

clearConsole = function() {
    var con= document.getElementById("console");
    while (con.childNodes.length) 
        con.removeChild(con.childNodes[0]);
},

log = function(msg) {
    var div= document.createElement("DIV"),
        text= document.createTextNode(msg),
        con= document.getElementById("console");
        
    div.appendChild(text);
    con.appendChild(div);
},

test = { "msg" : null, "data" : null };

var loaded= function() {
    if (!test.msg) 
        return setTimeout(loaded,10);
        
    log("loaded #" + loadCount + ": " + test.msg);
    
    var tmp;
    while (tmp = document.getElementById('JSONP')) {
        tmp.parentNode.removeChild(tmp);
        
        // not working in IE 7/8
        // for (var prop in tmp) delete tmp[prop];
        tmp = null;
    }
    
    test.msg = test.data = null;
    
    if (--loadCount) 
        setTimeout(load, 100);
};

var load = function(){
    var url= URL + (uuid ++);
    log("load via JSONP: "+url);
    
    script= document.createElement('script');       
    script.id = 'JSONP';
    script.type = 'text/javascript';
    script.charset = 'utf-8';
    script.src = url;
    head.appendChild(script);
    setTimeout(loaded,1000);
};
</script>
<div>
<button onclick="loadCount=3; load();" name="asd" value="asdas">jsonp load</button>
<button onclick="clearConsole();" name="asd" value="asdas">clear Console</button>
</div>
<div id="console"></div>
</body></html>

memoryleaktest.js

test.msg = "loaded #"+loadCount;
test.data = "test data with 1MB size";

You can recreate the memory leak by pasting the code into two files and open the Testing.html.

I used the Drip to track the leaks and in Drip you can see that the memory keeps increasing and the "<"script">" is not deleted.

Thank you very much for any help!

like image 802
zyzyis Avatar asked Mar 09 '11 10:03

zyzyis


1 Answers

Your question is already answered in the blog post you linked to. See the last paragraph.

As usual IE is the odd browser which requires a special case. IE doesn't like deleting native properties off of DOM nodes. Fortunately this doesn't matter, since IE allows one to reuse script tags. Just change the SRC property and it will fetch the new page immediately. Thus one only needs a single script tag in IE.

The code provided works in all browsers except IE, and in IE it's not an issue since you can just change the src property of the script tag and it will refire. So your code (for IE only) would just be:

var script = document.getElementById('JSONP');
if (!script) {
  [create it once]
}
script.src = URL + (uuid ++);
like image 191
Neil Fraser Avatar answered Nov 15 '22 00:11

Neil Fraser