| By Kurt Cagle | Article Rating: |
|
| March 19, 2007 03:00 PM EDT | Reads: |
5,302 |
This content is reprinted from Real-World AJAX: Secrets of the Masters published by SYS-CON Books. To order the entire book now along with companion DVDs for the special pre-order price, click here for more information. Aimed at everyone from enterprise developers to self-taught scripters, Real-World AJAX: Secrets of the Masters is the perfect book for anyone who wants to start developing AJAX applications.
Working with Asynchronous Server Content
One advantage comes from learning to work with JavaScript code asynchronously - it makes explaining the XMLHttpRequest object, arguably the cornerstone of AJAX, much easier.
Until roughly five years ago, working with the Web tended to be almost exclusively a one-way proposition - information flowed from the server to the client (the user agent or browser) and it did so only once. At least this was the way it appeared to most Web users and the vast majority of Web site designers. However, even this wasn't really the complete story. When you downloaded a Web page, the actual process was a little more complicated:
- The initial HTML page was downloaded and as it loaded it would be automatically parsed by the browser engine.
- If the HTML page contained images, then these images would be downloaded asynchronously under separate threads, and these threads would in turn also handle the rendering of the images to the browser page. The image rendering system would also check to make sure the images hadn't already been downloaded and made available in the browser cache.
- If objects were embedded using either the <object> or <embed> tag, these would also be downloaded asynchronously, and would typically run under separate processes that would do their own caching and download management.
- Finally, if iframes were used, the iframes would handle their own downloading process independent of the initial Web page.
Introducing the XMLHttpRequest
In 1999, Microsoft introduced a new object called the XMLHttpRequest() object designed to make it possible to open up a socket under user control. Unfortunately, the name is a misleading in several respects:
- While optimized for use with incoming XML content, it can in fact be used with any text content, including binary content that has been converted into some text representation (such as binHex).
- While it's been optimized for use with HTTP content, it can work with certain other protocols as well, depending on the implementation.
- Finally, while it was originally designed to request content from the server, it can, in fact, be used to send rich content, including XML and encoded binary, to the server as well.
In early 2006, there was so much momentum behind the XMLHttpRequest object implementation that the W3C established a Working Group to formalize this object as a standard. The specific interface for the XMLHttpRequest object is given in Table 2.10.
The XMLHttpRequest object solves a number of problems, not the least of which is the simple one of getting XML content into a DOM Object, or even into a Web page. For instance, if you needed to load a DOM from an external file (myXMLFile.xml) on the server (assuming it's in the same folder), you could retrieve it either synchronously as:
var http = new XMLHttpRequest();
http.open("GET", "myXMLFile.xml",false);
http.send(null);
var doc = http.getResponseXML;
or asynchronously as:
var doc = null;
var http = new XMLHttpRequest();
http.open("GET", "myXMLFile.xml",true);
http.onreadystatechange = function(
if (http.readystate == 4){
doc = http.getResponseXML;
}
}
http.send(null);
These represent the two forms (synchronous vs. asynchronous) of almost all XMLHttpRequest uses, but in the main are similar - open a connection, set the appropriate parameters, send the message, then wait for completion to get the response. The send() method can of course send content (as the name implies). But for HTTP GET calls, it more typically just sends a null value. (Note here that Internet Explorer assumes a null if you assign no parameters, but Mozilla doesn't. So in general you should always include the null value if dealing with cross-platform code).
The use of synchronous vs. asynchronous calls is important here. Synchronous calls are in-process calls, which means that the system basically freezes until some response comes back. If a connection is established but then fails, the HTTP object could potentially hang indefinitely, which is most convincingly a bad thing for your system's responsiveness.
Asynchronous calls, on the other hand, occur out-of-process, which means that while your code becomes more complex - your processing must be done in an invoked function rather than serially after the send() statement - you also have more control over things when they fail.
The control is further extended via the readyState property and the onreadystatechange event, the only event common to both Internet Explorer and Mozilla. The readyState property can hold one of four potential values, as shown in Table 2.11.
If you want to ensure that the content is completely usable, check to see that the readyState value has been set to 4, as shown in the asynchronous example above. (The synchronous example will only unblock the call once the readyState has been set to 4 implicitly, so no test is required there.)
The one thing you can't do with the events alone is to determine whether or not to call time-out or handle it if it does. Fortunately, this requires only a slight amendment to the asynchronous call:
var isProcessed = false;
var timeoutValue = 5000; // timeout in five seconds
var doc = null;
var http = new XMLHttpRequest();
http.open("GET", "myXMLFile.xml",true);
http.onreadystatechange = function(
if (http.readystate == 4){
doc = http.getResponseXML;
isProcessed = true;
}
}
var timeoutToken = window.setTimeout( function(){
if (!isProcessed){
alert("Download has timed out!");
http.abort();
}
window.clearTimeout(timeoutToken);
}, timeoutValue);
http.send(null);
In this case, a flag is set up (isProcessed) that determines whether the request is processed in the required interval. If it hasn't been, then a notification is sent and the HTTP process is aborted - the call is cleared and the HTTP object will take no further action. Then the original setTimeout() call is also cleared, though in this case that's not completely necessary (once the setTimeout function is processed, it will clear automatically).
As with fishing, simply because you have something on the line doesn't necessarily mean you've caught a fish. It's entirely possible, for instance, that the server can't find the Web page in question (the dread 404 error) and has instead sent a page back detailing this information. From personal experience, you can spend hours trying to figure out why your handy AJAX widget doesn't seem to want to display content, when a simple check of the server message might reveal that it's telling you that you've typed the wrong name for the filename.
As a consequence, you should check the status code after you've retrieved the content:
if (http.status != 200){
alert(statusText);
}
else {
doYourProcessing();
}
In general, the XMLHttpRequest system shares the same socket system as the rest of the browser. This means that when you download a resource from the Web, the browser will automatically cache this resource. This is great in those cases where the XML resources are static, but if you're dealing with a GET-based Web Service, cached content can prove to be a pain. Fortunately, you can shortcut this process by specifically setting request headers, not cache content, when it's requested - and specifically by setting the Cache-Control header to no-cache:
http.setRequestHeader("Cache-Control","no-cache");
While on the subject of Web Services, most such services (except SOAP-based ones) work by sending parameters to the server. In the case of GET-based services, you'd add the parameters to the query string. For instance, let's say that you had a Web Service that would return the currency exchange value between currencies, giving abbreviated names of the currencies.
If the service uses a GET-based protocol, you'd pass the parameters in the open method:
http.open("GET","http://www.currencyExchange.com/ws/convert?from=USD&to=CND&amount =10000");
http.setRequestHeader("Cache-Control","no-cache");
send(null);
If the content being submitted is fairly long (or if the Web Service expects it), you should use the POST method instead, sending the information as ampersand-delimited name/value pairs:
http.open("POST","http://www.currencyExchange.com/ws/convert");
http.setRequestHeader("Cache-Control","no-cache");
send("from=USD&to=CND&amount=10000");
Note that if you have an XML DOM object (xmlDom), you can set the Content-Type header to text/xml and send the DOM as XML:
http.open("POST","http://www.currencyExchange.com/ws/convert");
http.setRequestHeader("Content-Type","text/xml");
send(xmlDom);
It should be noted that while it's possible to use other HTTP commands beyond POST and GET (especially with the IE component), the WebDAV commands were generally not supported under Mozilla when this was written, so you should use such WebDAV extensions very carefully.
Additionally, the XMLHttpRequest is generally sandboxed in Web pages to work only with the same server as the Web page that the request was made from. This means that if you want to implement something like a news feed viewer, you either have to work outside of this context (say, in a browser extension) or use some kind of server-side redirect capability to work with specific feeds.
Finally, this chapter has assumed the use of Internet Explorer 6.0 Service Pack 2 or above for the IE implementation of the XMLHttpRequest stack, but if you're working with older versions of IE you have to invoke the object specifically as an ActiveX Control:
var http = new ActiveXObject("MSXML.XMLHttpRequest");
otherwise the interfaces are identical.
This content is reprinted from Real-World AJAX: Secrets of the Masters published by SYS-CON Books. To order the entire book now along with companion DVDs, click here to order.
Published March 19, 2007 Reads 5,302
Copyright © 2007 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
More Stories By Kurt Cagle
Kurt Cagle is a developer and author, with nearly 20 books to his name and several dozen articles. He writes about Web technologies, open source, Java, and .NET programming issues. He has also worked with Microsoft and others to develop white papers on these technologies. He is the owner of Cagle Communications and a co-author of Real-World AJAX: Secrets of the Masters (SYS-CON books, 2006).
- Kindle 2 vs Nook
- Cloud Computing on Gartner's Top 10 List and SYS-CON Events' 2010 Calendar
- Confessions of a Ulitzer Addict
- IBM Hardware Chief, Intel VC Exec Arrested in Insider Trading Scam
- Tactical Cloud Computing Panel at 1st Annual GovIT Expo
- Ulitzer.com Named Exclusive "New Media" Sponsor of Cloud Computing Conference & Expo
- Moving Your RIA Apps into the Cloud: Seven Challenges
- Adobe’s Aiming ColdFusion at Multiple Clouds
- Windows 7 – Microsoft’s First Step to the Cloud
- Ulitzer Provides a Powerful Social Journalism Platform
- Jill Tummler Singer, Deputy CIO of CIA, Keynotes at GovIT Expo
- Open Source Mobile Cloud Sync and Push Email
- Kindle 2 vs Nook
- The Difference Between Web Hosting and Cloud Computing
- Cloud Computing on Gartner's Top 10 List and SYS-CON Events' 2010 Calendar
- Ajax in RichFaces 3.3, JSF 2 and RichFaces 4
- Confessions of a Ulitzer Addict
- IBM Hardware Chief, Intel VC Exec Arrested in Insider Trading Scam
- My Thoughts on Ulitzer
- Tactical Cloud Computing Panel at 1st Annual GovIT Expo
- Ulitzer.com Named Exclusive "New Media" Sponsor of Cloud Computing Conference & Expo
- US Post Office Hops a Ride on NetSuite’s Cloud
- Moving Your RIA Apps into the Cloud: Seven Challenges
- Adobe’s Aiming ColdFusion at Multiple Clouds
- Building a Drag-and-Drop Shopping Cart with AJAX
- What Is AJAX?
- Google Maps! AJAX-Style Web Development Using ASP.NET
- Flashback to January 2006: Exclusive SYS-CON.TV Interviews on "OpenAjax Alliance" Announcement
- AJAXWorld Conference & Expo to Take Place October 2-4, 2006, at the Santa Clara Convention Center, California
- AJAX Sponsor Webcasts Are Now Available at AJAXWorld Website
- How and Why AJAX, Not Java, Became the Favored Technology for Rich Internet Applications
- "Real-World AJAX" One-Day Seminar Arrives in Silicon Valley
- AJAXWorld University Announces AJAX Developer Bootcamp
- AJAX Support In JadeLiquid WebRenderer v3.1
- Where Are RIA Technologies Headed in 2008?
- Struts Validations Framework Using AJAX





































