Browser keeps "connecting" after jQuery Ajax request times out

时间:2015-06-26 09:55:52

标签: jquery ajax

I have a list of IP addresses to a couple of servers that need to be pinged to see if they are running. Their IP addresses are stored in the data-ip-address attributes of a list of span elements, the Javascript function reads them in order, pings each of them, and displays the result. A more simplified version of the full function is this:

function pingServers() {
  if($('span[data-ping-this]').length > 0) {
    element = $('span[data-ping-this]:first');
    $(element).removeAttr('data-ping-this');
    var url = $(element).attr('data-ip-address');

    $.ajax({
      url: url, 
      dataType: 'jsonp',
      timeout: 4000,
      success: function(response) {
          displaySuccess();
      },
      error: function(something){
          displayWarning();
      }
    });

    setTimeout(function(){
      pingServers();
    }, 1000);
  }
}

The main thing is that there is a timeout defined, and that timeout definitely is working, because after 4 seconds of no response, I do get my warning displayed. But my browsers, both Firefox and Chrome, are still showing a status message that they are connecting (in the bottom-left corner). Firefox shows the Connecting to <ip address> message, while Chrome only shows Connecting..., and the favicon in the tab keeps being the animated loading icon.

If I keep the tab open, this goes on forever. If I change the tabs enough times, the status message (and the loading icon) eventually goes away (never without changing tabs). Another interesting thing is that, after it goes away, if I initiate this function again via Javascript (not by reloading the page), then the Connecting message doesn't show up at all anymore. Even though it should in this case. How I do this, is by simply returning the data-ping-this attribute to one of the span elements, and then run the function again.

$('span:first').attr('data-ping-this', 'true');
pingServers();

So, is this something that can be fixed on a jQuery side, and if so, how? Or is it a bug in the browsers?

1 个答案:

答案 0 :(得分:1)

Shortly: This is the bug of JSONP.

Explanation: The JSONP is not a real XmlHttpRequest, so it is not an Ajax call. JSONP is a hacky attempt to perform cross-domain requests by requesting some remote script from a different domain, see wikipedia to learn more.

What jQuery does inside, it performs this JavaScript call by adding

<script src='your_pinging_address'></script>

This is the only way to make a JSONP request. Then it comes to timeout, which they do most likely with setTimeout, so they found out on jQuery side that timeout is reached and they call your callback function; meanwhile the browser has no idea about this timeout because it is artificial, so it goes on waiting for a remote script.

In other words: every Ajax request but JSONP has a timeout on the browser side. The JSONP timeout is a piece of jQuery art.

I cannot point you to a line of the code where they serve the timeout in the current jQuery. I had a similar problem couple of years ago with some old jQuery version, but logically everything should stay as it was.