Hack 70. Set a Time Limit for the HTTP Request


Display a helpful message after a specified period of time if the XMLHttpRequest request has not succeeded.

The XMLHttpRequest object opens up a whole new bevy of exceptions that JavaScript programs can raise, having to do with the failure to connect successfully with the server. Why might this occur? Network latency might be the problem, or there might be something wrong with the server. You have no idea how fast your users' connections are, and the server-side program itself may be bogged down handling numerous simultaneous requests, or broken altogether. At any rate, as a developer, you want some control over how long your users wait for your application to respond. As we all know, chances are they won't be willing to wait very longa delay of much more than a few seconds is often considered unacceptable.

This hack waits 10 seconds for the server to respond before it displays a friendly message to the user.

Make it 5 seconds or less if you prefer, or 60. The maximum tolerable wait depends on the nature of your application, the results of your user testing, and other factors. For example, a customer from the general public might expect a more peppy application and be less willing to wait than an intranet user who is highly dependent on and invested in the application.


The hack uses the JavaScript method of the top-level window object named setTimeout( ).

Thanks to Joshua Gitlin and his article at http://www.xml.com/pub/a/2005/05/11/ajax-error.html for hints on this technique.


You can use window object methods without qualifying them with the window object. In other words, using setTimeout( ) alone works as well as using window.setTimeout( ).

setTimeout( ) takes a function name or literal as the first argument, then the number of milliseconds (1,000 per second) to wait before calling the method. It returns a numerical value that can be used to cancel the function call. I'll show you that in a moment; in the meantime, here is the code for http_request.js, which encapsulates the initialization and use of XMLHttpRequest. (See "Use Your Own Library for XMLHttpRequest" [Hack #3] for a comprehensive explanation.) Here is the the code, retrofitted to include setTimeout( ) and a new function, timesUp( ):

var request = null; var timeoutId; /* Wrapper function for constructing a request object.  Parameters:   reqType: The HTTP request type, such as GET or POST.   url: The URL of the server program.   asynch: Whether to send the request asynchronously or not.   respHandle: The name of the function that will handle the response.   Any fifth parameters represented as arguments[4] are the data a   POST request is designed to send. */ function httpRequest(reqType,url,asynch,respHandle){     //Mozilla-based browsers     if(window.XMLHttpRequest){         request = new XMLHttpRequest(  );     } else if (window.ActiveXObject){         request=new ActiveXObject("Msxml2.XMLHTTP");         if (! request){             request=new ActiveXObject("Microsoft.XMLHTTP");         }     }     //We test for a null request     //if neither ActiveXObject was initialized     if(request) {         //If the reqType parameter is POST, then the         //5th argument to the function is the POSTed data         if(reqType.toLowerCase(  ) != "post") {             initReq(reqType,url,asynch,respHandle);         } else {             //the POSTed data             var args = arguments[4];             if(args != null && args.length > 0){                 initReq(reqType,url,asynch,respHandle,args);             }         }     } else {         alert("Your browser does not permit the use of all "+               "of this application's features!");     } } /* Initialize a request object that is already constructed */ function initReq(reqType,url,bool,respHandle){     try{         /* Specify the function that will handle the HTTP response */         request.onreadystatechange=respHandle;         request.open(reqType,url,bool);         timeoutId = setTimeout(timesUp,10000);         //If the reqType parameter is POST, then the         //5th argument to the function is the POSTed data         if(reqType.toLowerCase(  ) == "post") {             request.setRequestHeader("Content-Type",                     "application/x-www-form-urlencoded; charset=UTF-8");             request.send(arguments[4]);         } else {             request.send(null);         }     } catch (errv) {         alert(                 "The application cannot contact "+                 "the server at the moment. "+                 "Please try again in a few seconds.\\n"+                 "Error detail: "+errv.message);     } } function timesUp(  ){ //see below...

The request.open( ) method prepares the XMLHttpRequest object for making an HTTP connection. Then the code calls setTimeout( ) just before the request is sent. Here's the rest of the code:

/* Event handler for XMLHttpRequest; this function is not a part of http_request.js, but would be defined in another code file that is using http_request.js, as in httpRequest("GET",url,true,handleReq);  */ function handleReq(  ){     if(request.readyState == 4){         //timeoutId is declared in http_request.js         //but can be referenced as a global var here         clearTimeout(timeoutId);             if(request.status == 200){                 //do cool stuff...             }     }//end outer if } function timesUp(  ){     request.abort(  );     alert("A problem occurred with communicating with "+           "the server program. Please make sure you are connected "+           "to the Internet and try again in a few moments."); }

Recall that setTimeout( ) calls the timesUp( ) function in 10 seconds. If 10 seconds pass without request.readyState == 4 returning true (meaning that the HTTP request is complete), which clears the timeout, timesUp( ) aborts the request and displays an alert window to the user. This action stops the request; the user will have to restart the interaction with the application to launch another request.

If you want to make the timeout three seconds instead, for example, the setup code looks like:

timeoutId = setTimeout(timesUp,3000);


If the HTTP request completes its network journey without a hitch, the code calls clearTimeout( ) with the aforementioned timeoutId as its parameter. This action cancels the call to timesUp( ) just in time, allowing the application to go on its merry way doing its intended job.




Ajax Hacks
Ajax Hacks: Tips & Tools for Creating Responsive Web Sites
ISBN: 0596101694
EAN: 2147483647
Year: 2006
Pages: 138

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net