Closing an IE popup two times while busy with Ajax request hangs IE

Closing an IE popup (twice) while a XmlHttpRequest is running, uses up all available connections.

To reproduce this:
- create a slow XmlHttpRequest (xhr). (Running about a minute or so)
- Open a popup window which executes this xhr. Close it while it’s still running
- Open this same popup again. (Second request). Directly close it while the xhr is running.
- Open another popup… et voila… IE Hangs..

This problem is what I was experiencing. After hours of frustrations we found a workaround:
In the onunload of the body tag you must call the “open” method on the same XmlHttpRequest object.
The call of “open” disconnects and stops the old request. Appearently abort doesn’t do this

Working code:

<html>
   <head>
   <script>
       var  xhr = new XMLHttpRequest();  // IE 7 only
       function runXHR() {
           document.body.style.backgroundColor = "red";
           xhr.open("POST", "http://gamecreatures.com/slowquery.php", true);
           xhr.onreadystatechange = function(transport) {
                if (xhr.readyState == 4 && xhr.status == 200 )  {
                     document.body.style.backgroundColor = "green";

                      alert("xhr done!");
            }}
            xhr.send("");
       }

       function closeXHR() {
           //xhr.abort();   // disbled
           // disconnect the connections:

           // !!! This is the solution, an open on the same object, closes the pending connection !!
           xhr.open("POST", "http://gamecreatures.com/whatever.php", true);   
       }
    </script>
   </head>
   <body onunload=“closeXHR()” “>
       <input type=”button” onclick=”runXHR()” value=”Execute XHR” />
   </body>
</html>

WARNING: This solution has only be tested with IE7!

Update 23-01-2008:

Solution for this problem with prototype is. Just put this code in an seperate javascript file. Include this file after prototype.js call iefix_runGarbageControl() in the onunload and the bug is fixed ;-)

// IE TCP/IP Connection Leak FIX, with prototype
if( Prototype.Browser.IE )
{
    var iefix_xhrs = new Array();
    function iefix_runGarbageControl() {
        for(var i=0; i<iefix_xhrs.length; i++) {
            try {
                iefix_xhrs[i].transport.onreadystatechange = Prototype.emptyFunction
                iefix_xhrs[i].transport.open( “GET”, “gamecreature”);
                iefix_xhrs[i] = null;
            } catch( e ) {}
        }       

    // Register responders
    Ajax.Responders.register({
        onCreate: function( xhr ) { iefix_xhrs.push( xhr ); },
        onComplete: function( xhr ) {
            for (var i=0; i<iefix_xhrs.length; i++) {
                if (iefix_xhrs[i] == xhr ) {
                    if (i<iefix_xhrs.length-1) {iefix_xhrs[i] = iefix_xhrs.pop();}
                    break;
                }
            }
        }
    });
}

Update 24-04-2008:
Added: place ‘iefix_runGarbageControl()’ in the onunload

2 Comments so far

  1. Johannes on April 24th, 2008

    Hi,

    I am running in the same problem in our application. We are using protoype as well, but I had trouble getting your fix to work. What version of prototype do you use?

    Thanks for the insight anyways.

    Johannes

  2. admin on April 24th, 2008

    The code wasn’t complete, you should put the ‘iefix_runGarbageControl()’ in the onunload.

    Or use prototype’s Event.observe:
    Event.observe(window,’unload’,iefix_runGarbageControl(),false);
    (please check prototype’s documenation. I only tested it with a call to iefix_runGarbageControl() in the onUnload)

    I believe at the time we were using version 1.6

    Btw I never solved the problem completely. For most situation is works perfectly. But when you are using iframes in a page that are performing XHR’s you’re in trouble..

    Btw. There are many, many more IE memory/garbage collection related bugs. But you probably found out already ;-)

Leave a reply