Async Requests over an Unreliable Network

If you need a professional responsive website that will help your business grow, then Bigfoot Media is the website design company you need. Based in Greenville SC, they are offer web design greenville sc for businesses across South Carolina and the nation.

The biggest void in the AJAX discussion, IMO, is how network and server availability affects XMLHttpRequests. I can only guess this void is a result of skill set – if you’re hot with CSS is issues relating to UI design, chances are you’re less fluent in the fine print of HTTP or used to thinking in terms of writing fault tolerant clients to remote services.

That gets further compounded by developing on localhost where you don’t get to see the impact of synchronous requests, for example, when the network or remote server is taking a break.

Question Time
Good news is there’s more discussion of such AJAX implementation details starting to appear, beginning with some excellent insight from Weiqi Gao in questioning AJAX and some concerns about the impact on development strategy from Bjorn Schott: AJAX: redesign your PHP applications?, with follow up from Marco Tabini in the anatomy of an AJAX framework. Yet more good stuff to be found in Ajax: It’s not all about XMLHTTPRequest (part I) and part 2.

Not Invented Here

Meanwhile one thing I keep seeing is comments like this one – not invented here – bloated: write my own. To some extent, fair enough and happen to like Alexander’s use of XMLHttpRequest because he has paid some attention to the impact the network may have on it.

But the point is, doing a “Hello World!”, directly against the ‘raw’ XMLHttpRequest API on localhost can be done with only a few lines of code. Unfortunately there’s more glue required before you can safely deploy it in the wild in a way that won’t drive users mad. And once you’ve repeated that glue a few times in a few places, you starting evolving your own “bloat”.

Issues with ASYNC requests in Live Environments

Getting back on track, there’s probably two major issues that occur to me with ASYNC requests, which aren’t solved “by default” by the XMLHttpRequest object.

  1. Dealing with Delay: if the network or remote server is taking it’s time, how does that relate to your AJAX application?
  2. Response Sequencing: network (or server) latency may vary over time. That means responses may not return in the order they were requested.

1. Dealing with Delay

In AJAX mistakes, Alex Bosworth makes reference to the problem with points 1. and 4.;

1. Not giving immediate visual cues for clicking widgets.

If something I’m clicking on is triggering Ajax actions, you have to give me a visual cue that something is going on. An example of this is GMail loading button that is in the top right. Whenever I do something in GMail, a little red box in the top right indicates that the page is loading, to make up for the fact that Ajax doesn’t trigger the normal web UI for new page loading.

4. Blinking and changing parts of the page unexpectedly

The first A in Ajax stands for asynchronous. The problem with asynchronous messages is that they can be quite confusing when they are pop in unexpectedly. Asynchronous page changes should only ever occur in narrowly defined places and should be used judiciously, flashing and blinking in messages in areas I don’t want to concentrate on harkens back to days of the html blink tag.

Alex is arguing this from the standpoint of an end user or a UI designer. Will aim to extend those points here with a practical step to help this.

First think it’s important to understand the effect by seeing it happen. Using the same Python server script from here, I modify the client script slightly to get it to place async requests instead or synchronous;

[code lang=”xml”]

Do it!

[/code]

Now if you save this as async1.html under my Python server’s directory (read this one again for longer instructions), and try clicking on that “doIt!” link a few times, you’ll see the sort of wierdness a delay on the server can cause.

Sometime you’ll get a response immediately. Other times it will take ages. Sometimes you’ll get this in your Javascript console (assuming Firefox);

[code]
Error: uncaught exception: [Exception…
“Component returned failure code: 0xc1f30001
(NS_ERROR_NOT_INITIALIZED) [nsIXMLHttpRequest.send]”
nsresult: “0xc1f30001 (NS_ERROR_NOT_INITIALIZED)”
location: “JS frame :: http://localhost:8000/async1.html
:: doIt :: line 42” data: no]
[/code]

That last one is caused by calling send() on an XMLHttpRequest object which is already processing an existing request. Will get to dealing with this problem in a minute…

Need for Tool: would really help people see the impact of latency on AJAX applications for themselves if there was tool to “slow” the network down. Any takers?

From my angle the easiest way to do this would be running a local HTTP proxy, through which your browser requests are tunnelled, and the responses are delayed by a small sleep() in the proxy.

Took half a shot at this by adding a filter to WebCleaner. Unfortunately WebCleaner has some internal mechanism to terminate connections which are taking too long, which killed my hack and my free moment. There’s a useful resource here on Python HTTP Proxies, some of which should be easy to hack. Would also be fairly easy to do with Perl’s HTTP::Proxy but a little messing in that area suggests that’s a *Nix only solution.

Anyway, the above example, if you try it, should give you a feeling for the sort of problems a delay can cause with async requests. The browser not longer “locks up” as it did with the sync requests, which is good, but the user get’s to keep on clicking stuff while wondering vaguely when the result will arrive.

Parting of solving this issue is giving visual feedback to the user – some kind of “in progess” status. But that’s not all – how long to you want to keep telling a user that they should keep waiting? If you’re not careful it could be in progress for a long long time – if the server delivers something like an HTTP ‘Content-Length’ header which is erroneously longer than the actual content you send, this could happen. To the end user, it’s likely that after a given number of seconds the request no longer bear relevance to what they’re doing – they’ve moved on to clicking other things and may be especially freaked out if a response shows up when they’d given up on it.

Timing Out

The usual approach, in other environments, where HTTP is being using is to implement some kind of timeout. If you’ve worked behind a corporate HTTP proxy, you’ve no doubt run into HTTP 504 status codes, where the proxy basically gave up trying to reach the web site you wanted it to.

Meanwhile most socket client APIs provide some kind of timeout setting you can control programmatically, like PHP’s fsockopen(). In fact it’s strange that XMLHttpRequest fails to offer this, but it’s fairly easy to add.

Uncaught Exception

Before adding a timeout capability to XMLHttpRequest, first going to solve the problem with that exception up there.

The fundamental problem is you can’t tell one XMLHttpRequest object to do two things at once and that’s solvable by using multiple instances of it, rather than the single global instance in the example above. In other words just create a new one whenever you need it. A note of fear and loathing here – have heard and possibly experienced strange things when lots of XMLHttpRequest objects are at work together. Have yet to really track it down – the exact circumstances / browser versions etc. unknown – whether it’s a garbage collection issue or what, I don’t know. Just be afraid 😉

So it might be you want to re-use an XMLHttpRequest object once it’s finished the current request, for the sake of a little efficiency. Solving this problem also makes timeouts easy to implement. So I can do it with a function that accepts an XMLHttpRequest instance and checks it’s ready state;

[code lang=”javascript”]
function callInProgress(xmlhttp) {
switch ( xmlhttp.readyState ) {
case 1, 2, 3:
return true;
break;

// Case 4 and 0
default:
return false;
break;
}
}
[/code]

Actually documented this here.

Now before calling send(), I can look first to see if the object is busy e.g.

[code lang=”javascript”]
if ( !callInProgress(xmlhttp) ) {
xmlhttp.send(null);
} else {
alert(“I’m busy. Wait a moment”);
}
[/code]

Aborting a Request

The XMLHttpRequest object also comes with an abort() method, to terminate the current request.

Only problem with abort(), as I remember (exact details purged from head and no desire to re-create circumstances) is if you call it on an object which isn’t processing a request (readyState 0 or 4) – weird things happen.

So the above callInProgess function can be useful.

Implementing Timeouts

Knowing all of the above, timeout can now be fairly easily implemented using window.setTimeout();

[code lang=”javascript”]
var timeoutId = window.setTimeout(
function() {
if ( callInProgress(xmlhttp) ) {
xmlhttp.abort();
}
},
5000 // Five seconds
);
[/code]

One catch here though, which I failed to mention here but implmented in JPSpan, is if you’re going to re-use the XMLHttpRequest object for another request, you need to remember to remove the timeout once the first request is completed, using
window.clearTimeout(), otherwise it will turn up to bite unexpectedly on a later request.

In the example I’ve been using, that would probably mean adding it to the callback function e.g.

[code lang=”javascript”]
// Callback
function handleResponse() {
if ( xmlhttp.readyState == 4 ) {

window.clearTimeout(timeoutId);

alert (xmlhttp.responseText);
}
}
[/code]

The only problem now is how we inform the end user (or the code that’s waiting for the response) that the request was timed out? Right now we’re just killing those requests quietly. Users probably need to know in some instances (like when they clicked “Save”) while code might like a chance to react, such as terminating that progress indicator or re-attempting the request.

Simply raising an exception from inside the anonymous function I registered with window.setTimeout() won’t work because there’s nothing in a position to catch it. Easier is probably calling some error reporting function e.g.;

[code lang=”javascript”]
function reportTimeout() {
// Fairly inexact but still something
alert(‘A request was timed out. Taking too long’);
}
[/code]

Now the timeout function becomes;

[code lang=”javascript”]
var timeoutId = window.setTimeout(
function() {
if ( callInProgress(xmlhttp) ) {
xmlhttp.abort();
reportTimeout();
}
},
5000 // Five seconds
);
[/code]

So timeouts are now possible but the quantity of extra glue is starting to rise…

2. Response Sequencing

Need a break from typing so will pick this up in detail some other time but consider this example which came up here;

Let’s say I’m showing a catalog that someone is shopping in, and asynchronously updating their shopping cart when they add items, sending an XMLHttpRequest message to the server and having it update the shopping cart display. Now let’s say the user wants one more item, adds it to the cart, and quickly clicks the checkout button… which one gets through first, the shopping cart add or the checkout?

It’s not safe to assume that your callback functions will be trigger in the same order that requests were made. If the “addToCart” operation takes a long time for the server to process, while “proceedToCheckout” is quick, it could well be that your “proceedToCheckoutHandler” function get’s called first.

Solving this needs some real glue, which I don’t have right now. Off the top of my head it needs some kind of queue to allow the responses to “fire” in the right order as well as a temporary “callback cache” which will likely need some tricks with Javascript closures.

More some other time…

FEATURED INFORMATION

In the recent years, webmasters are more aware about their websites search engine ranking and they are continuously making effort to improve it. Now many business web hosting companies provide the facility of search engine placement along with their regular services like unix hosting and virtual dedicated hosting etc. Also doing affiliation with online training authorities like cisco training and indulging in pay per click can not only increase ranking but also revenue.

Looking for moer information on getting your website to show up to your customers? Inbound marketing campaigns from Virginia SEO can help you, your website, and your business prosper!

28 Responses to Async Requests over an Unreliable Network
  1. Rachin Kapoor
    September 17, 2010 | 9:51 am

    Hey,
    Nice Blog!
    But I am having a strange problem:
    I am working on a web-app,which deals with managing 1000 plus entities.
    When I try to send a request with content length 29000 +, The request does not reach the server (one out of two times). This happens in Firefox only.

    After further investigation, I found out that the request was stuck in firefox (yes! it was stuck).

    If the user presses esc (which should abort the request by default in Firefox)
    The request is aborted in browser BUT BUT BUT the request immediately reaches the server. This behavior seen also seen when abort is called programmaticaly .

    Due to such behavior, client expects the request has not reached server, while it is actually reaching the sever?

    Can anyone help me understand why the request gets stuck on browser?

  2. iolanda
    February 5, 2010 | 12:52 am

    they’ve moved on to clicking other things and may be especially freaked out if a response shows up when they’d given up on it. CheckPoint certification

  3.       |>> Ajax Programmierung
    September 28, 2009 | 3:09 pm

    […] […]

  4. Alex
    April 24, 2009 | 9:00 am

    You can simulate a slow or buggy network on a Linux PC using the tc commands (often installed by default). See http://www.linuxfoundation.org/en/Net:Netem

  5. Jeff Paul Scam
    March 6, 2009 | 12:04 am

    Hi, I found your post really interesting, my friend and I run a small internet marketing business at home. We are roommates, so after our day job, we spend an hour on research and work.

  6. Chris
    February 5, 2009 | 9:10 pm

    Satish… see here for a resolution based on this for prototype… until they implement it.
    http://codejanitor.com/wp/2006/03/23/ajax-timeouts-with-prototype/

  7. Sathish
    November 5, 2008 | 10:22 pm

    How to implement this timeout when we use Prototype based ajax request
    eg.Ajax.Request(url..).How to implement the calinprogress function in this situation.

  8. SamOnes
    October 1, 2008 | 10:59 pm

    Did you hear? Russian agressor attacks USA…
    More info here: hotusanewx.blogspot.com

    SHOKED!!

  9. current science news event
    September 13, 2007 | 12:47 am

    current science news event…

    current science news event…

  10. Andrew Hedges
    August 23, 2007 | 6:31 pm

    Your last point about the shopping cart is similar to something I’ve just been working on (I’d provide a link to the site, but it’s yet to go live). Basically, the user clicks on dates on a calendar to indicate they want to stay at a hotel on those dates. I queue the requests and while they are running if the user tries to click the “book this room” button, she gets an alert saying her requests are still processing. It’s not the greatest, but it ensures we have all of the user’s intentions saved before letting them proceed to checkout.

  11. Darren M
    May 12, 2007 | 9:25 am

    I was getting this 0xc1f30001 error in firefox with a little bit of script that refreshed the content of a div every 15 seconds by calling a cgi on the server. sometimes the query to the server would get lost (here in south china.. that happens more than you might think..) and as soon as it tried to use the httpxmlrequest object again it would throw that error if the previous hadn’t returned yet, then quit the loop. the only way i’ve been able to get around it is to try() it and ignore it otherwise. this let’s it keep trying at least even if it can’t update during one loop. only tested in firefox. hopefully it helps at least one fellow JS newb ;p

    try {http.send(true);}
    catch (e) {
    //document.getElementById(“mydiv”).innerHTML = “danger, busy.. ” e;
    }

  12. Matt Emery
    November 3, 2006 | 6:11 am

    Use Netlimiter to throttle the speed on your browser (even when working on localhost).

  13. mike 18
    June 5, 2006 | 2:46 pm

    Houston always was Clemens’ most logical choice. He can stay home and follow his own program, remain in the same organization as his son, Class A third baseman Koby Clemens http://mike-18.blogspot.com/

  14. mike 18 boy gay video
    June 5, 2006 | 2:46 pm

    Houston always was Clemens’ most logical choice. He can stay home and follow his own program, remain in the same organization as his son, Class A third baseman Koby Clemens http://mike-18.blogspot.com/

  15. mike 18 young boy photo
    June 5, 2006 | 10:04 am

    Houston always was Clemens’ most logical choice. He can stay home and follow his own program, remain in the same organization as his son, Class A third baseman Koby Clemens http://mike-18.blogspot.com/

  16. […] After a little searching, I found a website that goes into what this error means and a way to fix it. I haven’t implemented any fix for this yet so there is no way to delete a contact (from the trial index page anyway) once it has been added. If you want to delete a contact, go here. […]

  17. dogergy
    April 23, 2006 | 9:59 am

    Best of the best,
    http://freestufflife.com/
    Apple 10 GB 2nd Generation iPod M8740LL/A. Every month draw between subscribers.

  18. huong
    April 11, 2006 | 9:23 pm

    jgdsl;jfkadflkjfkldsajf

  19. online directory main
    April 9, 2006 | 9:51 am

    hello! http://www.dirare.com/Sweden/ online directory. MY yellowpages, SMART Yellow Pages, About DIRare. From online directory .

  20. Ajaxian » Ajax Timeouts with Prototype
    March 24, 2006 | 10:32 am

    […] His version borrows ideas from a different post on handling the connection failure, but alters it a bit to get it to cooperate with a prototype setup. […]

  21. pongi
    March 12, 2006 | 9:17 am

    Hi, I’m new to JS and Ajax, but I’m using it to build the frontend for a (little) CMS. I’m not using so many istances of XmlHttpRequest at once (

  22. network intrusion detection
    February 22, 2006 | 2:25 pm

    I was searching the web and found your entry. I really like your site and found it worth while reading through the posts. I am looking to publish a comprehensive site reviewing many different articles and blog. Please feel free to take a look at my blog at network intrusion detection
    and add anything your want.

  23. Animal
    February 15, 2006 | 10:25 am

    Hmmm.. those smileys should be the numeral eight. Can you format code here?

    ::HLIGHT_BLOCK_1::

  24. Animal
    February 15, 2006 | 10:06 am

    How about this for handling server failures?

    if ((typeof XMLHttpRequest != “object”) && (typeof XMLHttpRequest != “function”))
    {
    function XMLHttpRequest()
    {
    try
    {
    return new ActiveXObject(“Msxml2.XMLHTTP”);
    }
    catch (e)
    {
    return new ActiveXObject(“Microsoft.XMLHTTP”);
    }
    }
    }

    /* Create an absolute URL out of a relative one.
    eg “foo.do” -> http://server/context/foo.do” */
    function makeURLAbsolute(url)
    {
    if ((url.substr(0, 7) != “http://”) && (url.substr(0, 8) != “https://”))
    {
    var base = window.location.href;
    var s;
    if (url.charAt(0) == “/”)
    {
    s = base.lastIndexOf(“/”) – 1;
    }
    else
    {
    s = base.indexOf(“/”, base.indexOf(“/”, 8) 1);
    }
    base = base.substr(0, s 1);
    return base url;
    }
    }

    /*
    Handle the response from a given URL with a given function.

    This function is asynchronous: It returns immediately

    Parameters
    url The URL to which the responseFunction is to respond..

    timeoutMillis Optional – defaults to 5 seconds. If the responseFunction
    parameter is being sent, send undefined as a placeholder.

    responseFunction Optional. A Javascript function to be called upon receipt
    of the server’s response.

    … Parameters to the response function.
    */
    function handleServerResponse(url, timeoutMillis, responseFunction)
    {
    var timeoutPassed = (typeof timeoutMillis == “number”);
    url = makeURLAbsolute(url);
    var newRequest = new XMLHttpRequest();
    var requestId = setTimeout(function(){serverResponseFailure(newRequest);}, timeoutPassed ? timeoutMillis : 5000);
    newRequest.open(“GET”, url “&requestId=” requestId, true);
    if (typeof responseFunction == “function”)
    {
    var requestResponseArgs = [];
    if (arguments.length > 3)
    {
    requestResponseArgs = arguments.slice(3);
    }
    newRequest.onreadystatechange = function()
    {
    if (newRequest.readyState == 4)
    {
    clearTimeout(requestId);
    if ((newRequest.status > 199) && (newRequest.status

  25. John
    January 28, 2006 | 4:36 am

    Nice article. Helped me in my hunt for that cryptic error message from firefox. Your piece of code was just what I was looking for. Thanks!

  26. Anonymous
    December 15, 2005 | 6:18 am

    your code is wrong here..

    function callInProgress(xmlhttp) {
    switch ( xmlhttp.readyState ) {
    case 1, 2, 3:
    return true;
    break;

    // Case 4 and 0
    default:
    return false;
    break;
    }
    }

    that doesn’t work right.. it worked in IE but not FF.. it needs to be..

    function callInProgress(xmlhttp) {
    switch ( xmlhttp.readyState ) {
    case 1: case 2: case 3:
    return true;
    break;

    // Case 4 and 0
    default:
    return false;
    break;
    }
    }

  27. […] “Async Requests over an Unreliable Network” […]

  28. […] t in far more succinct terms than I’ve been cautiously trying to do in some of these blogs. The more I think about it, the more it’s clear th […]