After I was done writing my previous post XMLHttpRequest Leak in IE 7/8 I suddenly remembered that I had missed the ‘abort’ method of ‘XMLHttpRequest’.
It means what it says:-) It aborts the current call.
Many a times I want to do some housekeeping either before or after calling the ‘abort’ method. To make the housekeeping transparent I will usually end up over-riding ‘abort’ before exposing it. Many libraries do it including jQuery. Consider the following code:
<html> <head> <title>xmlHttpRequest Leak, Abort Override Demo</title> <script> function makeAjaxCall(){ var xhr = new XMLHttpRequest(); xhr.open('GET', 'test1.php', true); xhr.onreadystatechange = function (event){ if(xhr.readyState == 4 && xhr.status == 200){ //clean up to avoid leaks xhr.onreadystatechange = new Function; xhr = null; } }; //override abort here var oldAbort = xhr.abort; xhr.abort = function() { if ( xhr ) { oldAbort.call( xhr ); } //some housekeeping code //----- //----- }; xhr.send(null); return xhr; } var xhr = makeAjaxCall(); //To abort I would call xhr.abort(); </script> </head> <body> </body> </html>
Note that I have over-ridden the abort method. Nothing fancy or tricky here.
Just to make sure everything is OK I am going to create a test to check for any leaks. Here is the test case you are probably familiar with by now:
leak-test4.html
<html> <head> <title>xmlHttpRequest Leak, Abort Override Demo</title> <script> var interval; var i = 1000; function fire(){ interval = setInterval(makeLeak, 50); } function makeLeak(){ var xhr = new XMLHttpRequest(); xhr.open('GET', 'test1.php?i='+i, true); xhr.onreadystatechange = function (event){ if(xhr.readyState == 4 && xhr.status == 200){ //cleanup to avoid leaks xhr.onreadystatechange = new Function; xhr = null; if(--i === 0){ clearInterval(interval); interval = null; alert('All Done'); } } }; var oldAbort = xhr.abort; xhr.abort = function() { if ( xhr ) { oldAbort.call( xhr ); } //housekeeping code //---- //------ }; xhr.send(null); return xhr; } </script> </head> <body> <button id = "button1" onclick="fire(false);">Fire</button> </body> </html>
Running this in sIEve produces the following:
It seems there is a leak. I confirmed that I had cleaned up by putting the following code in the ‘xhr.onreadystatechange’ callback handler. What went wrong now?
xhr.onreadystatechange = new Function;
xhr = null;
Well I did not do a thorough job of cleaning up!. It seems I forgot to use my own advice. Like I mentioned in my previous post, you need to clean up functions you over-ride. I need to clean up ‘abort’ by adding the following:
xhr.abort= new Function;
My ‘xhr.onreadystatechange’ handler will now look like this:
xhr.onreadystatechange = function (event){ if(xhr.readyState == 4 && xhr.status == 200){ //cleanup to avoid leaks xhr.onreadystatechange = new Function; xhr.abort = new Function; //clean up abort override xhr = null; if(--i === 0){ clearInterval(interval); interval = null; alert('All Done'); } } };
Having done that, this is what I get from sIEve

Notice that the leak has stopped.
Remember, always cleanup after yourself.
Happy computing!
[…] I continue I want to encourage you to read my previous posts XMLHttpRequest Leak in IE 7/8 and xmlhttprequest-leak-in-ie-78-forgot-the-abort-thing to fully understand my reasoning in this […]
LikeLike