Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (6.5 MB, 505 trang )
346
Part IV AJAX and Server-Side Integration
such title is Microsoft ASP.NET 3.5 Step By Step (Microsoft Press, 2008). For others, look at
http://www.microsoft.com/mspress for more information.
If you’re developing a server-side application using other technologies such as the LAMP
(Linux, Apache, MySQL, Perl/PHP/Python) stack, searching the web for tutorials is likely the
easiest way to get up to speed quickly on development on the platform. The book Learning
Perl (O’Reilly, 2005) is a great resource for learning the basics of the Perl programming
language.
Note If you like my writing style, I wrote Beginning Perl Web Development (Apress, 2005), which
focuses on using Perl to work with web applications.
PHP’s main website (http://www.php.net) is a good place to start for information on PHP, and
for Python, take a look at the Python website (http://www.python.org).
The XMLHttpRequest Object
The XMLHttpRequest object is central to building an AJAX application. Although implementations of JavaScript differ, the ECMAScript and the World Wide Web Consortium (W3C) have
standardized many aspects of it except the XMLHttpRequest object, which has never been
subject to a standardization process. Even so, since the release of Windows Internet Explorer
7, you use the XMLHttpRequest object in the same way across all major browsers.
Microsoft first implemented the XMLHttpRequest object in Microsoft Internet Explorer 5.0. If
a visitor is using a browser version earlier than that, applications using XMLHttpRequest won’t
work. In Internet Explorer versions prior to version 7, the XMLHttpRequest object was instantiated as an ActiveXObject object, but other browsers implemented the XMLHttpRequest
object as a JavaScript object built into the browser. This means that if your applications need
to work with versions of Internet Explorer earlier than version 7, you need to instantiate the
XMLHttpRequest object for those browsers in a different way, as I show you later in the chapter. The next section, “Instantiating the XMLHttpRequest Object,” shows how you can test for
the existence of XMLHttpRequest and how to instantiate it in all versions of Internet Explorer.
Instantiating the XMLHttpRequest Object
Internet Explorer 7 and later versions, and all other major browsers that support
XMLHttpRequest, instantiate the XMLHttpRequest object in the same way:
var req = new XMLHttpRequest();
Chapter 19 A Touch of AJAX
347
For Internet Explorer versions earlier than version 7, you must instantiate an ActiveXObject
instead. However, the way you do this varies depending on the version of the XMLHTTP
library installed on the client. Therefore, you need to do a bit of code juggling to instantiate
an XMLHttpRequest object in these earlier versions of Internet Explorer.
The code in Listing 19-1 is a cross-browser function that instantiates an XMLHttpRequest
object across multiple browsers.
Listing 19-1 Instantiating an XMLHttpRequest object across browsers.
function readyAJAX() {
try {
return new XMLHttpRequest();
} catch(e) {
try {
return new ActiveXObject("Msxml2.XMLHTTP");
} catch(e) {
try {
return new ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {
return "A newer browser is needed.";
}
}
}
}
The function in Listing 19-1 uses multiple levels of try/catch blocks to instantiate an
XMLHttpRequest, regardless of whether the visitor is using Internet Explorer or another
browser. If the native call to XMLHttpRequest fails, that means that the visitor is using an
Internet Explorer browser older than version 7. In such a case, the error is caught and one
of the methods for instantiating XMLHttpRequest that is based on ActiveXObject is tried. If
none of these methods succeed, the likely reason is that the browser is too old to support
XMLHttpRequest.
The article “About Native XMLHTTP” on MSDN describes some of the version history and
security nuances of the XMLHttpRequest object in Internet Explorer. This article can be found
at http://msdn2.microsoft.com/en-us/library/ms537505.aspx.
You call the readyAJAX() function shown in Listing 19-1 like this:
var requestObj = readyAJAX();
The requestObj variable now contains the XMLHttpRequest object returned by the function,
or, if the function couldn’t create the object, the requestObj variable contains the string
“A newer browser is needed.”
348
Part IV AJAX and Server-Side Integration
Sending an AJAX Request
With a newly created XMLHttpRequest object in hand, you can send requests to the web
server and get responses. To send the request, you use a combination of the open() and
send() methods of the XMLHttpRequest object.
There are two fundamentally different ways to send AJAX requests: synchronously and asynchronously. When sent in a synchronous manner, the requesting code simply waits for the
response—a process called blocking. So, for a synchronous request, the requesting code will
block, effectively preventing further processing or execution of other JavaScript while the
script waits for the response from the web server. This process has obvious disadvantages
when the request or response gets lost in transit or is just slow. With asynchronous requests,
the requesting code doesn’t block. Instead, the caller can check the request status to discover
when the request has completed. You see more about asynchronous requests later in this
chapter; it’s easier to work with synchronous requests first.
Before you can send a request, you have to build it. To do that, you use the open method,
which has three arguments: the request method (GET, POST, HEAD, or others), the Uniform
Resource Locator (URL) to which the request will be sent, and a Boolean true or false, indicating whether you want to send the request asynchronously or synchronously, respectively.
Assuming that your request object has been retrieved using the readyAJAX() function and
placed into a variable named requestObj, a typical asynchronous call to the open method
might look like this:
var url = "http://www.braingia.org/getdata.php";
requestObj.open("GET", url, true);
That same call, sent synchronously, looks like this:
var url = "http://www.braingia.org/getdata.php";
requestObj.open("GET", url, false);
You actually send the request with the send method, as follows:
requestObj.send();
Note If the parameters sent with the request have any special characters, such as spaces or other characters reserved by the URI RFC, you must first escape those characters using the % notation. This is discussed further in RFC 3986, which you can find at ftp://ftp.rfc-editor.org/in-notes
/rfc3986.txt. You can also find more information at http://msdn2.microsoft.com/en-us/library
/aa226544(sql.80).aspx.
Chapter 19 A Touch of AJAX
349
How the Web Works in 500 Words or Fewer
The Hypertext Transfer Protocol (HTTP) is the language of the web. HTTP is currently
defined by RFC 2616 and describes a protocol for exchanging information by using
requests from clients and responses from servers.
Requests from clients such as web browsers contain a specific set of headers that define
the method used for retrieval, the object to be retrieved, and the protocol version to be
used. Other headers contain the web server host name, languages requested, the name
of the browser, and other information that the client deems relevant to the request.
Here’s a basic HTTP version 1.1 request that shows only the most important of these
headers:
GET / HTTP/1.1
Host: www.braingia.org
This request specifies the GET method to retrieve the document located at the / (root)
directory location using HTTP version 1.1. The second line, commonly called the Host
header, is the URL http://www.braingia.org. This header tells the web server which website is being requested. Several different methods can be used in a request; the three
most common are GET, POST, and HEAD. The client and server also exchange HTTP
cookies as part of the headers. Cookies are sent in the request, and others might be
received in the response.
When the web server for http://www.braingia.org receives a request like this, the web
server sends response headers that indicate how it has handled the request. In this
case, the web server sends response headers similar to these:
HTTP/1.1 200 OK
Date: Sat, 12 Mar 2011 01:04:34 GMT
Server: Apache/1.3.33 (Debian GNU/Linux) mod_perl/1.29 PHP/4.3.10-22
Transfer-Encoding: chunked
Content-Type: text/html; charset=iso-8859-1
The requested document follows the response headers. The first and most important
header indicates the status of the response. In the example, the response is 200, which
is synonymous with OK. Other common responses include 404 (which indicates that the
requested document was not found), 302 (which indicates a redirect), and 500 (which
indicates that a server error occurred).
Understanding these basics of HTTP is important for understanding how to build AJAX
requests and how to troubleshoot those requests when things go wrong. You can find
more information about HTTP, including the various response codes, in RFC 2616 at
ftp://ftp.rfc-editor.org/in-notes/rfc2616.txt.
350
Part IV AJAX and Server-Side Integration
Processing an AJAX Response
It’s easier to work with the response when the request is sent synchronously, because the
script’s execution stops while awaiting the response. The requestObj variable provides helpful
methods for processing a response, including giving access to the status codes and text of
the status sent from the server. Regardless of whether the request is synchronous or asynchronous, you should evaluate the status code to ensure that the response was successful
(usually indicated by a status of 200).
The responseText method contains the text of the response as received from the web server.
For example, assume a server application returns the sum of two numbers. Calling the application to add the numbers 2 and 56 looks like this:
http://www.braingia.org/addtwo.php?num1=2&num2=56
Here’s a synchronous call and response retrieval:
requestObj.open("GET", "http://www.braingia.org/addtwo.php?num1=2&num2=56", false);
requestObj.send();
if (requestObj.status == 200) {
alert(requestObj.responseText);
} else {
alert(requestObj.statusText);
}
In this example, assume that the requestObj was created using the readyAJAX() function that
you saw earlier. The preceding code then calls the open method using a GET request to the
specified URL (http://www.braingia.org/addtwo.php?num1=2&num2=56). The request is sent
synchronously because the last argument to the open method is false. Next, the code calls
the send method, which actually sends the request to the web server.
When the client receives the response from the web server, it calls the status method to
check the status value. If the response code is 200, indicating success, the code displays the
responseText, which holds the response from the server. If the response status code is anything other than 200, the code displays the status text.
Processing an asynchronous response is a bit more complex. When a request is sent asynchronously, script execution continues. Therefore, it is unpredictable when the script will be
notified that the response has been received. To know the response status, you can use the
onreadystatechange event to trigger code that checks the event’s readyState property to
determine the state of the request/response cycle. Recall from Chapter 17, “JavaScript and
XML,” that the readyState property has five states, as shown in Table 19-1.
Chapter 19 A Touch of AJAX
Table 19-1 Values
351
for the readyState Property
Value
Description
0
Uninitialized. Open but has yet to be called.
1
Open. Initialized but not yet sent.
2
Sent. The request has been sent.
3
Receiving. The response is actively being received.
4
Loaded. The response has been fully received.
For practical purposes, the only state that matters to the JavaScript and AJAX programmer is
state 4—Loaded. Attempting to process a response that has a readyState value other than 4
results in an error.
You typically use an anonymous function to handle the onreadystatechange event for
asynchronous AJAX calls. The function checks to see whether the readyState property has
reached 4, and then checks to ensure that the status is 200, indicating success. The code
follows this format:
requestObj.onreadystatechange = function() {
if (requestObj.readyState == 4) {
if (requestObj.status == 200) {
alert(requestObj.responseText);
} else {
alert(requestObj.statusText);
}
}
}
In this next exercise, you create an XMLHttpRequest object and send a request to a web
server to retrieve a book title based on its ISBN. You need a web server and web server
code to print the response, because requests sent using XMLHttpRequest are subject to the
JavaScript same-origin policy.
The same-origin policy requires that requests go only to servers within the same domain
from which the calling script was loaded. In other words, because I’m executing the script in
this exercise directly from my web server at http://www.braingia.org, my script is able to call
that server and retrieve a response. If you tried to call a URL on another web server, however,
the same-origin policy would prevent the script from retrieving the response.
Note One way to get around the same-origin security feature is to use an HTTP proxy or to
write the server-side program so that it sends a request on behalf of the calling program; however, learning how to do that is beyond the scope of this book.
For the upcoming exercise, the script or program running on the server needs to return the
phrase “JavaScript Step by Step” when it receives a GET request with a name/value argument
with the following value:
352
Part IV AJAX and Server-Side Integration
isbn=9780735624498
For example, at its most basic, the server-side program could look like this when implemented
inside an Active Server Pages (ASP) page based on VBScript:
<%
dim isbn
isbn=Request.QueryString("isbn")
If isbn<>"" Then
If isbn=="9780735624498" Then
Response.Write("JavaScript Step by Step")
End If
End If
%>
A functionally similar program looks like this if written in PHP:
$isbn = $_GET[‘isbn'];
if (! $isbn) {
print "That request was not understood.";
} else if ($isbn == "9780735624498") {
print "JavaScript Step by Step";
}
?>
In the following exercise, the URL to which the request will be sent is predefined, but you
must replace that URL with the URL where your server-side program is located. Because of
the same-origin policy, the server-side program needs to be within the same domain as the
page that calls it.
Sending and receiving with XMLHttpRequest
1. Create your server-side program to return the book title when it receives the isbn argument shown earlier. You can do this in your choice of languages. (If you need to, look at
the two examples shown earlier.)
2. Using Microsoft Visual Studio, Eclipse, or another editor, edit the file isbn.htm in the
Chapter19 sample files folder (in the companion content).
3. Within the webpage, replacing the TODO comment with the following code shown in
boldface (in the isbn.txt file in the companion content). Be sure to replace the url variable with the appropriate URL for your server-side program:
"http://www.w3.org/TR/html4/strict.dtd">