views:

1188

answers:

3
for (var i = 0; i < 5; ++i) {
  var xhr;
  if (window.XMLHttpRequest) {
    xhr = new XMLHttpRequest();
  } else if (window.ActiveXObject) {
    xhr = new ActiveXObject("Msxml2.XMLHTTP");
  }
  xhr.open('GET', '/Test/LongOperation?p=' + new Date());
  xhr.send('');
}

This is only a demo (not live code) but it illustrates the core problem. LongOperation is a method that returns a result after 10 seconds.

Questions:

  1. Why does IE8 (and maybe other IEs) hang when the user tries to navigate away from page right after the above code snippet has been executed? FireFox/Safari cancel these requests and allow navigation to another page. If you replace 'i < 5' with 'i < 4' then IE would not hang.

  2. How to work around this ugly IE behavior? Users are very upset when their browser suddenly hangs.

+3  A: 

Most browsers have an inbuilt limit of 4 connections to any given server. One way to work around this "problem" might be to use a different hostname for out of band XML requests - your user requests will go to the main hosts, while the AJAX requests can go to the second server.

1800 INFORMATION
AFAIK limit is 2 unless they've changed the default behaviour in IE 8. I doubt that because I'm pretty sure RFC indicates that "2 concurrent connections to one server."
dr. evil
Best way to understand if this is the problem, find the related registry change the concurrent connection number and try again, see if it still hangs.
dr. evil
Thanks for help. About registry, I know about this 'feature' but I cannot force users to change necessary setting in registry on their machine.About limit, FireFox also have similar limits, but it do not hangs. Limit means that when it (limit) is reached further requests aren't send to the server until some pending request have been completed, but they _are_ queued and _will_ be executed. The problem is with IE: if IE has such _queued_ requests browser hangs when navigating away from page.
Roman
The limit was changed to 6 in IE8 for non-modem users. When you say "hang" however, I suspect you actually mean "remains responsive but does not navigate to a page on the same server, instead the progress donut just spins"?
EricLaw -MSFT-
A: 

Try running them asynchronously and then triggering the next http request when the each completes. I suspect that the xmlhttp request is blocking the UI thread of IE whereas the implementations of that on other browsers is a little more graceful.

Hopefully that will give you a work-around for question 2 but I can only guess at the true reason for question 1, it could just be a bug.

Neil Trodden
A: 

My answer to my question. I abort all not completed xhr objects in window.onbeforeunload. At least this solution works for me. I slightly override $.ajax() method behavior:

;(function($) {
    var rq = [];
    var ajax = $.ajax;
    $.ajax = function(settings) {
        // override complete() operation
        var complete = settings.complete;
        settings.complete = function(xhr) {
            if (xhr) {
                // xhr may be undefined, for example when downloading JavaScript
                for (var i = 0, len = rq.length; i < len; ++i) {
                    if (rq[i] == xhr) {
                        // drop completed xhr from list
                        rq.splice(i, 1);
                        break;
                    }
                }
            }
            // execute base
            if (complete) {
                complete.apply(this, arguments)
            }
        }

        var r = ajax.apply(this, arguments);
        if (r) {
            // r may be undefined, for example when downloading JavaScript
            rq.push(r);
        }
        return r;
    };

    // 'kill' all pending xhrs
    $(window).bind('beforeunload', function() {
        $.each(rq, function(i, xhr) {
            try {
                xhr.abort();
            } catch(e) {
                $debug.fail('failed to abort xhr');
            }
        });
        rq = [];
    });
})(jQuery);

$debug - my utility class

Roman