bulletproof ajax: XMLHttpRequest

ajax作者发表的论文:http://www.adaptivepath.com/ideas/ajax-new-approach-web-applications

The Ajax Toolkit

The XMLHttpRequest object is the engine that drives Ajax, but it doesn’t exist in a vacuum. As Jesse James Garrett said in his original essay, “Ajax isn’t  a technology. It’s really several technologies, each flourishing in its own right,
coming together in powerful new ways.”

ANY SERVER-SIDE LANGUAGE
  Chances are, you want your application to respond intelligently to a visitor’s  input. The server needs to be able to make decisions about what specific  information needs to be sent to the browser. In order to do that, you need to
use some kind of programming language on the server.

XML?
You’d be forgiven for thinking that XML was a crucial component of Ajax applications.The term XMLHttpRequest itself, as well as its long-windedness, is  somewhat misleading.
XML, which stands for eXtensible Markup Language, is a format for describing  data. Ajax applications require some kind of structured format to deliver  information from the server to the client. But XML is just one option. As we’ll
see later on, there are other ways of structuring data that are equally viable for Ajax.

注意:ajax不一定要用到xml

Valid markup
It’s entirely possible to build an Ajax application without using XML. But
there is another kind of markup language that is fundamental to any Web
site, with or without Ajax.
HyperText Markup Language (HTML) is the lingua franca of the World Wide
Web. It is used to give semantic structure to content on the Web. After the
content itself, markup is the most important and valuable tool for creating
Web pages.

In some ways, it’s easier to explain what Ajax isn’t:
Ajax is not a specific technology.
■ Ajax is not an acronym.
Instead, Ajax is a methodology方法,理论。ajax不是一项技术,而是一项方法. It’s a way of working with a set of ingredients 组成部分,材料to create a more usable, responsive experience on the Web. Some of those ingredients are based on the server, but the majority are browser-based technologies:

ajax组成:少部分基于server,大部分基于browser。
■ HTML or XHTML
■ CSS
■ DOM Scripting
■ XMLHttpRequest
The XMLHttpRequest object is the glue that binds the server to the browser. Before looking at this mysterious object in more detail, it’s important to have  a good grounding in the Web Standards upon which Ajax is built.

获取

XMLHttpRequest对象
function getHTTPObject() {
var xhr = false;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
return xhr;
}

It is still possible that the getHTTPObject function has returned a value of  false, meaning that the browser executing the script does not have Ajax  capabilities. If you explicitly check for this, you can make sure you won’t be
asking older browsers to execute code beyond their ability:
var request = getHTTPObject();
if (request) {
// do some Ajax
}

The getHTTPObject function works fine most of the time. But it does contain
an assumption. Just because a browser supports ActiveX doesn’t necessarily
mean that the specific ActiveX object for Ajax also exists.

This is the case with Internet Explorer 5 for Mac. As it stands, the
getHTTPObject function throws an error in that browser.
One solution might be to look at the user-agent string of the browser and check
its name and version number. This is called browser sniffing浏览器嗅探. It’s a very bad
idea. User-agent strings can be spoofed哄骗, and browser sniffing inevitably triggers
false positives. Object detection is always preferable to browser sniffing.
In this particular case, you can use object detection to test only for the existence
of ActiveX, not for a particular type of ActiveX object.

最好的办法:

function getHTTPObject() {
    var xhr = false;
    if (window.XMLHttpRequest) {
        xhr = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
        try {
                xhr = new ActiveXObject("Msxml2.XMLHTTP");
        }catch(e){
            try{
                xhr=new ActiveXObject("Microsoft.XMLHTTP");
            }catch(e){
                xhr=false;
            }
        }
    }
    return xhr;
}

onreadystatechange 事件由服务器触发。It is the handler for an event that istriggered not by the user, but by the server.

During an Ajax operation, the server sends updates to the client about
the current status of the communication. This is done by updating a property
of the XMLHttpRequest object. The property is called readyState,
which we’ll study in more detail later in this chapter. What interests us
now is the fact that every time the readyState property is changed, the
readystatechange event is triggered.

Whenever the onreadystatechange event handler captures this event, it
means something is happening on the server. Changing the readyState
property is the server’s way of pinging the client.
If you attach a function to the onreadystatechange event handler, that
function will be executed every time the server pings the client with an
update. Here’s an example:

var request = getHTTPObject();
if (request) {
request.onreadystatechange = doSomething;
}
I’m assigning a reference to a function called doSomething to the
onreadystatechange event handler. The doSomething function will be
executed every time the readystatechange event is triggered.

I’ve specified what I want to happen when the server sends an update to the
client. I still need to specify exactly what I want from the server。

Send a Request To a Server

 open(method,url,async)

Specifies the type of request, the URL, and if the request should be handled asynchronously or not.

method: the type of request: GET or POST
url: the location of the file on the server
async: true (asynchronous) or false (synchronous)

url可以是绝对或相对路径。

The file you are requesting must reside in the same domain as the JavaScript
file that is making the request. (这点很重要)If the JavaScript file is being executed from
foo.com, it cannot request a file from bar.com. Later on, I will show you some
ways of getting around this security restriction, but for now, it’s best to think
of XMLHttpRequest as being domain-specific.

You can specify a Boolean value as the third argument for the open method.
This indicates whether the request should occur asynchronously or not.
If you specify a value of true, then the script will make an asynchronous
request. This means it won’t wait for a response from the server before moving
on to the rest of the script.
If you specify a value of false, then the processing of the script will stop at
that point. The script won’t resume until the Ajax request is completed.

第3个参数基本上都是true。

SEND
The open method specifies the details of an Ajax request, but it doesn’t initiate
the request.(open发生没有发送request) Use the send method to fire off a request that you have prepared
using the open method.
The send method takes a single argument. You can pass it a string of data
that will then be sent to the server.
If you are using the GET request method, don’t send any data. Instead, pass a
value of null to the send method:
  request.send(null);

If you need to send data to the server, use the POST request method. Send
the data as a query string like this:
name=Jeremy+Keith&message=Hello+world
  A query string is made up of name-value pairs joined by ampersands. Each
name and value should be URL-encoded. That means spaces become plus
signs and non-alphanumeric characters need to be encoded as hex values.
The @ symbol becomes %40, for example.
To send data, you need to use one more method of the XMLHttpRequest
object.

setRequestHeader
When a Web browser requests a page from a Web server, it sends a series
of headers along with the request. These headers are bits of metadata that
describe the request. A header is used to declare whether a request is GET
or POST.
This ability to send headers can be reproduced in an Ajax request using a
method called setRequestHeader. This method accepts two arguments

 setRequestHeader(header,value)

If you are sending data to the server with a POST request, you need to set the
value of the "Content-type" header to
"application/x-www-form-urlencoded":
  request.setRequestHeader("Content-type", "application/
x-www-form-urlencoded");
This lets the server know that data is being sent, and that the data has been
URL-encoded.

A complete Ajax POST request looks like this:

Receive a Response

READYSTATE
The readyState property indicates the current state of an Ajax request. Its
value is numerical:
■ 0 Uninitialized. The open method hasn’t been called yet.
■ 1 Loading. The open method has been called, but the send method hasn’t.
■ 2 Loaded. The send method has been called. The request has begun.

3 Interactive. The server is in the process of sending a response.
■ 4 Complete. The server has finished sending a response.

Every time the value of readyState changes, the readystatechange event
is triggered. If a function has been assigned to the onreadystatechange
event handler, it will be executed every time readyState changes value。

Rather than trying to do anything clever with the changing readyState property,
it’s best just to wait until its value has reached 4. Then you know the
server has finished sending a response.

function doSomething() {
if (request.readyState == 4) {
// do something with the response
}
}

The doSomething function will be executed more than once because it has
been assigned to the onreadystatechange event handler:
request.onreadystatechange = doSomething;
Every time the readyState property changes, doSomething is executed,
but the if statement in the function ensures that nothing will happen until
readyState has a value of 4.

STATUS
In the same way that a Web browser sends headers with each request it makes,
a Web server sends headers with each response it sends. (服务器发送的header信息)These headers contain
information about the server, as well as information about the document
being served. This information includes the document’s content type (HTML,
XML, and so on) and character encoding (utf-8, iso-8859-1, and so on).
The most important header sent with any response from a Web server is the
status code. This three-digit numerical value, which the server sends with
every response to a request, is part of the HyperText Transfer Protocol (HTTP)

that drives all communication on the Web. I’m sure you’re familiar with the
404 status code, which translates to “Not Found.” Some other codes are 403
for “Forbidden,” and 500 for “Internal Server Error.”

The most common status code is 200, which means “OK.” This code indicates
that the server successfully sent the requested resource.
In the XMLHttpRequest object, the status code sent by the server is available
as a property called status. By comparing this property to a value of
200, you can be sure that the server has sent a successful response

function doSomething() {
if (request.readyState == 4) {
if (request.status == 200) {
// the response was sent successfully
}
}
}

By adding an else clause, you can also deal with situations where everything
doesn’t go according to plan:

function doSomething() {
if (request.readyState == 4) {
if (request.status == 200) {
// the response was sent successfully
} else {
// something went wrong!
}
}
}

200 isn’t the only server code that indicates a successful response. A value of
304 translates as “Not Modified.” (304没修改)The server sometimes returns this response
if a browser performs what’s known as a conditional GET request. The Opera
browser uses conditional GET requests. In this situation, the server may return
a response of 304, indicating that the document hasn’t changed since it was
last requested, so the browser can safely use a cached version

更好的函数:

function doSomething() {
if (request.readyState == 4) {
if (request.status == 200 || request.status == 304) {
// the response was sent successfully
} else {
// something went wrong!
}
}
}

RESPONSETEXT
The responseText property of XMLHttpRequest contains the data sent
from the server. It is a string. Depending on what the server is sending, this
might be a string of HTML, a string of XML, or just a string of text.
The complete responseText property is available when the readyState
property reaches four, indicating that the Ajax request is complete:

function doSomething() {
if (request.readyState == 4) {
if (request.status == 200 || request.status == 304) {
alert(request.responseText);
}
}
}

RESPONSEXML
If the server is sending back XML, then this data will be available in a property
called responseXML. The responseXML property will be available only
if the server sends the data with the correct headers.(responseXML当服务器发送了正确的header才可用) The MIME type must be text/xml.  In the next chapter, I will show you how to parse XML from the responseXML
property.

一个简单的实例:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
<script>
function getHTTPObject() {
    var xhr = false;
    if (window.XMLHttpRequest) {
        xhr = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
        try {
                xhr = new ActiveXObject("Msxml2.XMLHTTP");
        }catch(e){
            try{
                xhr=new ActiveXObject("Microsoft.XMLHTTP");
            }catch(e){
                xhr=false;
            }
        }
    }
    return xhr;
}


function grabFile(file)
{
     var request=getHTTPObject();
     if(request)
     {
         request.onreadystatechange = function() {
                displayResponse(request);
         };
         request.open("GET", file, true);
         request.send(null);
     }
}

function displayResponse(request)
 {
     if(request.readyState==4)
     {
         if(request.status==200||request.status==304)
         {
             alert(request.responseText);
         }
     }
 
}

      
   </script>
</head>

<body>
<body>
<p>
<a href="example.txt" onclick="grabFile(this.href); return false;">
Click here to see the contents of a text file
</a>
</p>
</body>
</html>

点击链接会输出文本内容。

原文地址:https://www.cnblogs.com/youxin/p/2661262.html