views:

184

answers:

1

I have a situation where my website needs to quickly retrieve data from my server via AJAX.

My website runs on port 80, serving normal web pages. I normally run my AJAX server on port 8001 (I use JSONP and this works fine). This works for most users. However, some users are blocked from high ports by their local firewalls.

In order to allow people who have outgoing connections on port 8001 blocked to use my website, I want to fall back onto port 80 in case the user is unable to get a response on port 8001.

The reason I do not use port 80 all the time is that sometimes people have "smart" anti-virus gateways or other application level firewalls which intercept outgoing connections on port 80. These add a couple hundred milliseconds to my roundtrip time. My AJAX service needs to minimize the roundtrip response time.

I use jQuery to make working with XMLHttpRequest simple. I am using the JSONP variant, and that piece works - pulling AJAX requests from a different IP address or port is no problem in and of itself.

The idea I have is that when the page first loads, it fires off 2 getJSON calls. One to port 8001 and another to port 80. The same response handler is used in both calls.

The first call the response handler sets my "portToUse" variable and then proceeds with normal functionality.

This works when port 8001 is not blocked. If port 8001 is blocked, this works as well. However, there is an about 5 second delay before my response from port 80 comes back. This is not caused server side. I would like to eliminate this delay.

My theory is that even though getJSON is asynchronous, the browser only fires off one XMLHttpRequest at a time. It waits before the first one either returns or times out before sending the next one.

I am not sure if I am right. If I am, then is there a way to bypass this functionality and fire off both XMLHttpRequest at the same time? If I am wrong, do you have a suggestion as to what could be causing the delay in receiving my second response (from port 80 on my server)? Any and all other suggestions are welcome as well.

EDIT: This behavior only happens in Firefox 3 and Opera 9.63. IE7 and Chrome do not exhibit this delay.

+3  A: 

AJAX calls occur simultaneously.

I would set global var portToUse = 80 (default) and setup a function that calls out on port 8001 to fetch a very small amount of data. If the ajax request returns successfully on 8001, then change portToUse = 8001;

The requests you start making immediately will go out on 80 until you know 8001 is open. Then it will switch and all future requests will be made on 8001.

You could also do this:

var request = $.ajax({ 
                      type: 'POST', 
                      url: 'test.html:8001',
                      success: function(){ portToUse = 8001; }
                     });

setTimeout(function(){

    request.abort();

}, 1000);

So if the request takes longer than a second, we cancel the request all together and your requests continue to use port 80. You could set that timeout value to anything, depending on how much time you want to allow the request attempt. 500 would be 500ms and so on...

a432511
That may work. However, if the delay I am experiencing in FF still happens, I will have this behavior: req->80:20ms, req->8001->never comes back,2nd req->80:5020ms (because it was delayed by the timed out req to 8001), 3rd req->80:20ms,etc. This would not be acceptable either.
the timeout in the request on 8001 should not affect your other requests. I am going to edit my answer and offer another approach...
a432511