Handling timeouts gracefully in AJAX using client-side code

This question was posted to the AZGroups list:

Has anyone come up with a solution for handling timeout issues related to
AJAX, especially with regard to allowing the user to cancel a request?  This
includes cancelling the response to the client as well as notifying
the server that the request has been cancelled, allowing the server to
possibly kill the request process.

AJAX comes in many flavors, so for this sample I'll just write the most generic callback code possible in Javascript using XMLHttpRequest.  No library necessary, this shows all the actual guts to do an asynchronous callback, with the addition of testing for timeout.  Once you understand this approach, you can then check out your AJAX library of choice to see how it uses XMLHttpRequest, and then add on this timeout code there.  The crux of the solution is to use a setTimeout() at the same time you issue the send(), and have the setTimeout() call your own custom timeout function that does an XMLHttpRequest.abort() like this:

<SCRIPT language=javascript>
// Needed for IE6 and older to replicate the standard XMLHttpRequest object
if (window.ActiveXObject && !window.XMLHttpRequest){window.XMLHttpRequest =
 function(){progIds=new Array("Msxml2.XMLHTTP.6.0","Msxml2.XMLHTTP.5.0",
 "Msxml2.XMLHTTP.4.0","Msxml2.XMLHTTP.3.0","Msxml2.XMLHTTP",
 "Microsoft.XMLHTTP");for(i in progIds){try{return new
 ActiveXObject(progIds[i]);}catch(ex){alert(progIds[i]);}}return null;};}

// Standard asynchonous AJAX code
var xhr = new XMLHttpRequest();
// You would normally trade out the location.href with an actual .ashx
// page.  It's like this here only for testing, thereby requesting this
// same page back from the server.
xhr.open("POST",location.href,true);

// The function that will be called asynchronously when the server sends
// back its response
xhr.onreadystatechange=function(){
   // If you're using the file system instead of a web server then xhr.status
   // will come back as 0, not 200.  And of course if the page isn't found
   // then a web server will send back a status of 404.  xhr.readyState is 4
   // when the page is done.
   if (xhr.readyState == 4 && xhr.status == 200) {
      clearTimeout(xhrTimeout);   // Looks like we didn't time out!
      // Use xhr.responseText to parse the server's response
      alert(xhr.responseText);
   }
}

// Now that we're ready to handle the response, we can make the request
xhr.send("My excellent post info");
// Timeout to abort in 5 seconds
var xhrTimeout=setTimeout("ajaxTimeout();",5000);
function ajaxTimeout(){
   xhr.abort();
   alert("Well dang, the AJAX request timed out.  Did you lose network "+
         "connectivity for some reason?");
   // Note that at this point you could try to send a notification to the
   // server that things failed, using the same xhr object.
}
</SCRIPT>

Hope that helps!  This is the same kind of thing that GMail is doing when you see the “Oops...  Unable to reach the server...” message.  It doesn't try to pester the server again with a callback if it times out, though.


Feedback

# re: Handling timeouts gracefully in AJAX with client-side code

My saving grace:

Anyone reading this and implementing should make certain they check the XmlHttpRequest object ("xhr" in this example) for null before running, since a browser might not support it. (but, who cares about them ;) 3/7/2006 9:14 AM | Eric Swanson

# re: Handling timeouts gracefully in AJAX using client-side code

Exactly what I was looking for. Thanks! 11/6/2007 4:05 AM | Dan

# re: Handling timeouts gracefully in AJAX using client-side code

Works great if you only have one Ajax request on the page. If you have multiple -- more than the concurrent requests setting of the browser-- then this wont work. Say you have 5 ajax calls on a page, but your browser only allows 2 concurrent connections. If you put the setTimeout on anything but readyState 2, requests 3, 4, and 5 will timeout prior to their specified time. 4/17/2008 10:48 AM | Tim

# re: Handling timeouts gracefully in AJAX using client-side code

Works perfect. Thank you from the bottom of my heart, it was just what I was looking for. 7/23/2008 4:10 PM | Truma

# re: Handling timeouts gracefully in AJAX using client-side code

Thank you very much buddy.Your solution really helped me a lot... :) 7/21/2009 11:42 AM | Virajith

# re: Handling timeouts gracefully in AJAX using client-side code

Use clearTimeout(xhrTimeout) on onreadystatechange = 4 (success.) You could do an onclick=(xhr.abort()) somewhere if you wish. For multiple AJAX instances I used an array - for timeouts, objects, and update ids. Communicating this to the onreadystatechange function requires some juggling (since by default, it is stateless, I think...)

Anyway, thanks. This was very helpful! 9/1/2009 8:02 AM | RiverC

# ed hardy shop

If you have multiple -- more than the concurrent requests setting of the browser-- then this wont work. 10/23/2009 3:11 AM | ed hardy

# re: Handling timeouts gracefully in AJAX using client-side code

The above video link seems to be broken. 11/6/2009 11:29 PM | DDos Protection

Post a comment





 

News


Welcome to my blog.
Here's what we've got on the menu today:

Tag Cloud


Article Categories

Archives

Post Categories

Image Galleries

Syndication: