Ajax|javascript| Request | asynchronous
Open Request
When you have a URL to connect to, you can configure the request. You can do this by using the open () method of the XMLHttpRequest object. The method has five parameters:
- Request-type: The type of request sent. A typical value is a get or POST, but a head request can also be sent.
- URL: The URL to connect to.
- Asynch: True if you want to use an asynchronous connection, false otherwise. The parameter is optional and the default is true.
- Username: If authentication is required, you can specify the user name here. The optional parameter has no default value.
- Password: If authentication is required, you can specify a password here. The optional parameter has no default value.
The first three parameters are usually used. In fact, you should specify that the third argument is "true" even if an asynchronous connection is required. This is the default value, but it is easier to understand whether the request is asynchronous or synchronous.
By combining these, you usually get a line of code as shown in Listing 9.
Listing 9. Open Request
function GetCustomerInfo () {
var phone = document.getElementById ("Phone"). Value;
var url = "/cgi-local/lookupcustomer.php?phone=" + Escape (phone);
Request.open ("Get", url, True);
}
Once the URL is set, the other is simple. Most requests use get is enough (in a later article will see the need to use POST), plus the URL, which is the use of the open () method all the required.
Challenge the asynchronous nature
In the next article in this series, I'll spend a lot of time writing and using asynchronous code, but you should understand why the last parameter of open () is so important. In a general request/response model, such as Web 1.0, a client (a browser or code running on a local machine) makes a request to the server. The request is synchronized, in other words, the client waits for a response from the server. When the client waits, at least some form of notification will be given to you waiting:
- An hourglass (especially on Windows).
- A spinning ball (usually on a Mac machine).
- The application is basically frozen, and then the cursor changes over time.
That's why Web apps are awkward or slow--the lack of real interactivity. When the button is pressed, the application actually becomes unused until the request that was just triggered is answered. If a request requires a large number of server processing, the waiting time can be long (at least in a world where the multiprocessor, DSL is not waiting).
Asynchronous requests do not wait for the server to respond. The application continues to run after the request is sent. Users can still enter data in a Web form, or even leave the form. There is no rotating ball or hourglass, and the application is not significantly frozen. The server quietly responds to the request and tells the original requester that the work is over (and will soon be seen). As a result, the application feels less sluggish or slower, but responds quickly, interacts, and feels much faster. This is only part of the WEB 2.0, but it is an important part of it. All the old-fashioned GUI components and Web design paradigms cannot overcome slow, synchronous request/response models.
Send Request
Once you have configured it with open (), you are ready to send the request. Fortunately, the name of the method that sent the request is more appropriate than open (), which is send ().
Send () has only one parameter, which is the content to send. But before considering this method, recall that the previous data has been sent through the URL itself:
var url = "/cgi-local/lookupcustomer.php?phone=" + Escape (phone);
Although you can send data using Send (), you can also send data through the URL itself. In fact, a GET request (about 80% of a typical Ajax application) is much easier to send data with a URL. If you need to send security information or XML, you may want to consider sending content using Send () (Security data and XML messages are discussed in subsequent articles in this series). If you do not need to pass the data through send (), you can pass NULL as a parameter to the method. So you'll find that in the examples in this article you only need to send a request like this (see listing 10).
Listing 10. Send Request
function GetCustomerInfo () {
var phone = document.getElementById ("Phone"). Value;
var url = "/cgi-local/lookupcustomer.php?phone=" + Escape (phone);
Request.open ("Get", url, True);
Request.send (NULL);
}
Specifying callback methods
Only a few of the things we do now are new, revolutionary or asynchronous. It must be admitted that the small keyword "true" in the Open () method establishes an asynchronous request. But beyond that, the code is no different from programming in Java servlet and JSP, PHP, or Perl. So what's the biggest secret of Ajax and Web 2.0? The secret lies in XMLHttpRequest a simple attribute onreadystatechange.
First of all, be sure to understand the process in these codes (please review listing 10 if necessary). Establish its request and then issue the request. Also, because it is an asynchronous request, the JavaScript method (GetCustomerInfo () in the example) does not wait for the server. So the code will continue to execute, that is, exit the method and return control to the form. Users can continue to enter information and the application will not wait for the server.
This raises an interesting question: what happens when the server completes the request? The answer is that nothing happens, at least for the current code! Obviously this doesn't work, so the server needs some indication of what to do after it completes the request sent to it via XMLHttpRequest.
Now it's time for the onReadyStateChange attribute to debut. This property allows you to specify a callback function. Callback Allow server (guess?) The code in the Web page is called in reverse. It also gives the server a certain degree of control, and when the server completes the request, it looks at the XMLHttpRequest object, especially the onReadyStateChange property. Then call any method specified by the property. This is called a callback because the server initiates a call to the Web page, regardless of what the Web page is doing. For example, the method may be invoked when the user sits in the chair without touching the keyboard, but it may also be invoked when the user enters, moves the mouse, scrolls the screen, or clicks a button. It doesn't care what the user is doing.
This is what is called asynchronous: The user operates the form on one level, while the server responds to the request and triggers the callback method specified by the onReadyStateChange property on the other layer. So you need to specify the method in code like listing 111.
Listing 11. Set callback method
function GetCustomerInfo () {
var phone = document.getElementById ("Phone"). Value;
var url = "/cgi-local/lookupcustomer.php?phone=" + Escape (phone);
Request.open ("Get", url, True);
Request.onreadystatechange = Updatepage;
Request.send (NULL);
}
What you need to pay special attention to is where the property is set in code--it is set before send () is called. This property must be set before the request is sent, so that the server cannot view the property until it has answered the request for completion. Now the only thing left is to write the Updatepage () method, which is the focus of the last verse of this article.
Handling Server Responses
Sending the request, the user is happy to use the Web form (while the server is processing the request), and now the server completes the request processing. The server views the onReadyStateChange property to determine the method to invoke. In addition, you can treat your application as if it were another application, whether asynchronous or not. In other words, you don't have to take a special action to write a response to the server, just change the form, give the user access to another URL, or do whatever it takes to respond to the server. In this section we will focus on the response to the server and a typical action-to instantly change the part of the form that the user sees.
Callbacks and Ajax
Now we've seen how to tell the server what to do: Set the onReadyStateChange property of the XMLHttpRequest object to the name of the function to run. That way, the function is called automatically when the server finishes processing the request. There is no need to worry about any of the parameters of the function. Let's start with a simple method, as shown in Listing 12.
Listing 12. Code for the callback method
<script language= "javascript" type= "Text/javascript" >
var request = false;
try {
Request = new XMLHttpRequest ();
} catch (Trymicrosoft) {
try {
Request = new ActiveXObject ("Msxml2.xmlhttp");
} catch (Othermicrosoft) {
try {
Request = new ActiveXObject ("Microsoft.XMLHTTP");
} catch (Failed) {
Request = false;
}
}
}
if (!request)
Alert ("Error initializing xmlhttprequest!");
function GetCustomerInfo () {
var phone = document.getElementById ("Phone"). Value;
var url = "/cgi-local/lookupcustomer.php?phone=" + Escape (phone);
Request.open ("Get", url, True);
Request.onreadystatechange = Updatepage;
Request.send (NULL);
}
function Updatepage () {
Alert ("Server is done!");
}
</script>
It simply gives you a few simple warnings about when the server has completed the task. Experiment with the code in your own Web page and open it in the browser (see listing 8 if you want to see the XHTML in this example). Enter the phone number and leave the field, and you will see a pop-up warning window (shown in Figure 3), but click OK to show up again ...
Figure 3. Ajax Code for pop-up warnings
Depending on your browser, you will see two, three, or even four warnings before the form stops popping up warnings. What's going on here? It turns out we haven't considered the HTTP ready state, which is an important part of the request/response loop.
HTTP Ready State
As mentioned earlier, the server finds the method to invoke in the XMLHttpRequest onReadyStateChange property after the request is completed. It's true, but it's not complete. In fact, it calls this method whenever the HTTP ready state changes. What does that mean? You must first understand the HTTP ready state.
The HTTP ready state indicates the status or situation of the request. It is used to determine whether the request has started, whether a response has been received, or whether the request/response model has been completed. It can also help determine if the response text or data provided by the server is safe to read. You need to understand five ready states in an AJAX application:
- 0: The request was not issued (before calling open ()).
- 1: The request has been established but has not been issued (before send () is called).
- 2: The request has been sent out in process (it is usually possible to get the content head from the response).
- 3: The request has been processed and there is usually some data available in the response, but the server has not completed the response yet.
- 4: The response is complete, you can access the server response and use it.
As with most cross-browser issues, the use of these ready states is inconsistent. You may expect the task readiness status to be from 0 to 1, 2, 3, and then 4, but in practice it is rarely the case. Some browsers never report 0 or 1 and start directly from 2, then 3 and 4. Other browsers report all the states. Others report ready State 1 more than once. As you can see in the previous section, the server calls Updatepage () multiple times, and every call pops up a warning box--possibly different from what you expected!
For Ajax programming, the only state that needs to be handled directly is ready state 4, which indicates that the server response is complete and that the response data is safe to use. Based on this, the first line in the callback method should look like the one shown in Listing 13.
Listing 13. Check Ready status
function Updatepage () {
if (request.readystate = 4)
Alert ("Server is done!");
}
The modification will ensure that the server's processing is complete. Try running the new version of the Ajax code, and now you'll see that the warning message is displayed just as expected.
HTTP Status Code
Although the code in Listing 13 looks good, there is a problem-what if the server responds to the request and finishes processing but reports an error? You know, server-side code should understand that it is invoked by Ajax, JSP, plain HTML forms, or other types of code, but only with traditional Web-specific method reporting information. In the Web World, HTTP code can handle a variety of problems that may occur in a request.
For example, you must have encountered a 404 error code when you entered the wrong URL request, which means that the page does not exist. This is just one of the many error codes that HTTP requests can receive (see the links in resources for a complete list of status codes). It is also common to indicate that 403 and 401 of the data being accessed are protected or blocked access. In either case, these error codes are obtained from the completed response. In other words, the server fulfills the request (that is, the HTTP ready state is 4) but does not return the data expected by the client.
Therefore, in addition to the ready state, you need to check the HTTP status. We expect the status code to be 200, which means everything goes well. If the ready state is 4 and the status code is 200, you can process the server's data, and that data should be the required data (not the wrong or other problematic information). It is also necessary to increase the state check in the callback method, as shown in Listing 14.
Listing 14. Check the HTTP status code
function Updatepage () {
if (request.readystate = 4)
if (Request.status = 200)
Alert ("Server is done!");
}
To add more robust error handling and try to avoid being overly complex, you can add one or two status code checks, take a look at the modified Updatepage () version in Listing 15.
Listing 15. Add a bit of error checking
function Updatepage () {
if (request.readystate = 4)
if (Request.status = 200)
Alert ("Server is done!");
else if (Request.status = 404)
Alert ("Request URL does not exist");
Else
Alert ("Error:status code is" + Request.status);
}
Now change the URL in GetCustomerInfo () to a nonexistent URL to see what happens. You should see a warning message stating that the URL requested does not exist--great! It's hard to handle all the error conditions, but this small change can cover 80% of the problems in a typical WEB application.
Read response text
Now you can ensure that the request has been processed (through the ready state), the server gives a normal response (through the status code), and finally we can process the data returned by the server. The returned data is saved in the ResponseText property of the XMLHttpRequest object.
The textual content in responsetext, such as format and length, is intentionally ambiguous. This allows the server to set the text to any content. For example, one script might return a comma-delimited value, the other would use a value separated by a pipe character (that is, a | character), and one would return a long text string. Where to go depends on the server.
In the example used in this article, the server returns the customer's last order and the customer's address, separated by a pipe character in the middle. Then use the order and address to set the element values in the form, listing 16 shows the code to update the display.
Listing 16. Handling Server Responses
function Updatepage () {
if (request.readystate = = 4) {
if (request.status = =) {
var Response = Request.responseText.split ("|");
document.getElementById ("Order"). Value = Response[0];
document.getElementById ("Address"). InnerHTML =
Response[1].replace (/\n/g, "
");
Else
alert ("Status is" + Request.status);
}
}
First, get the responsetext and use the JavaScript split () method to separate from the pipe character. The resulting array is placed in the response. The first value in the array--the last order--accessed with response[0], is set to the value of the field with the ID ' order '. The second value response[1], which is the customer address, requires a little more processing. Because the lines in the address are delimited by a normal row delimiter ("\ n" character), the code needs to be replaced with XHTML-style line delimiters. The substitution process is done using the Replace () function and the regular expression. Finally, the modified text acts as the internal HTML in the HTML form div. The result is that the form is suddenly updated with the customer information, as shown in Figure 4.
Figure 4. Break Neck form after receipt of customer data
Before I finish this article, I'll also introduce another important attribute of XMLHttpRequest Responsexml. If the server chooses to use an XML response, the attribute contains (perhaps you have guessed) the XML response. Processing XML responses differs greatly from normal text processing, involving parsing, document Object Model (DOM), and other issues. XML is further described in later articles. But since Responsexml is often discussed with responsetext, it is necessary to mention it. ResponseText is enough for many simple AJAX applications, but you'll soon see that XML can be handled well with AJAX applications.
Conclusion
You may be a bit tired of xmlhttprequest, and I rarely see an entire article discussing an object, especially this simple object. However, you will use this object repeatedly in every page and application that you write with Ajax. Frankly speaking, there is something to be said about XMLHttpRequest. The next installment describes how to use POST and get in a request to set the content header in the request and read the content header from the server response, understanding how to encode the request and process XML in the request/response model.
In the future, we'll introduce the common Ajax Toolbox. These toolkits actually hide many of the details described in this article, making Ajax programming easier. You might think, since there are so many toolkits, you have to encode the underlying details. The answer is that if you don't know what your application is doing, it's hard to find problems in your application.
So don't ignore these details or simply browse, if the handy and gorgeous toolbox is wrong, you don't have to scratch your head or send a mail request to support it. If you know how to use XMLHttpRequest directly, you'll find it easy to debug and solve the strangest problems. The toolbox is a good thing only if you let it solve your problem.
So please familiarize yourself with XMLHttpRequest. In fact, if you have Ajax code that uses the toolbox, you can try rewriting it using the XMLHttpRequest object and its properties and methods. This is a good exercise to help you better understand the rationale.