44-JavaScript高级程序设计-XMLHttpRequest对象

Ajax

Ajax:Asynchronous JavaScript + XML 的简写,虽然名字包含 XML,但 Ajax 通信与数据格式无关。
【无须刷新页面即可从服务器取得数据】
核心:XMLHttpRequest 对象 (简称 XHR)

一、XMLHttpRequest对象

IE5 是第一款引入 XHR 对象的浏览器。在 IE5 中,XHR 对象是通过 MSXML 库中的一个 ActiveX 对象实现的。(旧款浏览器不多讨论)

IE7+、Firefox、Opera、Chrome 和 Safari 都支持原生的 XHR 对象。
创建 XHR 对象
var xhr = new XMLHttpRequest();

1. XHR的用法

open():启动请求
3个参数:要发送的请求的类型(“get”、"post"等)、请求的 URL 和表示是否异步发送请求的布尔值。
xhr.open("get", "example.php", false);
说明:
URL 相对于执行代码的当前页面(当然也可以使用绝对路径);
调用 open() 方法并不会真正发送请求,只是启动一个请求以备发送。
注意:
只能向同一个域中使用相同端口和协议的 URL 发送请求。

send():发送请求
1个参数:要作为请求主体发送的数据。
send(null);
注意:如果不需要通过请求主体发送数据,必须传入 null,因为这个参数对有些浏览器来说是必需的。

收到响应后,响应的数据会自动填充 XHR 对象的属性。

responseText:作为响应主体被返回的文本。
responseXML:如果响应的内容类型是"text/xml"或"application/xml",这个属性中将保存包含着响应数据的 XML DOM 文档。
status:响应的 HTTP 状态。
statusText:HTTP 状态的说明。

接收到响应后,第一步检查 status 属性,以确定响应已经成功返回。
一般来说,可以将 HTTP 状态代码为 200 作为成功的标志。此时,responseText 属性的内容已经就绪,在内容类型正确的情况下,responseXML 也应该能够访问了。
状态代码为 304 表示请求的资源并没有被修改,可以直接使用浏览器中缓存的版本。(也意味着响应是有效的)。

发送异步请求,检测 XHR 对象的 readyState 属性,该属性表示请求 / 响应过程的当前活动阶段。

0:未初始化。尚未调用 open() 方法。
1:启动。已经调用 open() 方法,但尚未调用 send() 方法。
2:发送。已经调用 send() 方法,但尚未接收到响应。
3:接收。已经接收到部分响应数据。
4:完成。已经接收到全部响应数据,而且已经可以在客户端使用了。

readystatechange 事件:readyState 属性的值变化时就会触发
注意:必须在调用 open() 之前指定 onreadystatechange 事件处理程序,才能确保跨浏览器兼容性。

abort():在接收到响应之前,取消异步请求
xhr.abort();
调用后,XHR 对象会停止触发事件,也不再允许访问任何与响应有关的对象属性。
在终止请求之后,还应该对 XHR 对象进行解引用操作。由于内存原因,不建议重用 XHR 对象。

2. HTTP头部信息

XHR 对象提供了操作两种头部(请求头部和响应头部)信息的方法。

默认情况下,在发送 XHR 请求的同时,还会发送下列头部信息。
不同浏览器实际发送的头部信息会有所不同,但下列信息基本上是所有浏览器都会发送的。

Accept:浏览器能够处理的内容类型。
Accept-Charset:浏览器能够显示的字符集。
Accept-Encoding:浏览器能够处理的压缩编码。
Accept-Language:浏览器当前设置的语言。
Connection:浏览器与服务器之间连接的类型。
Cookie:当前页面设置的任何 Cookie。
Host:发出请求的页面所在的域 。
Referer:发出请求的页面的 URI。
User-Agent:浏览器的用户代理字符串。

setRequestHeader():设置自定义的请求头部信息。
2个参数:头部字段的名称和头部字段的值。
注意1:要成功发送请求头部信息,必须在调用 open() 方法之后且调用 send() 方法之前调用 setRequestHeader()。
注意2:建议使用自定义的头部字段名称,不要使用浏览器正常发送的字段名称,否则有可能会影响服务器的响应。有的浏览器允许重写默认的头部信息,但有的浏览器不允许这样做。

getResponseHeader():传入头部字段名称,取得相应的响应头部信息。
getAllResponseHeaders():取得一个包含所有头部信息的长字符串。
在服务器端,也可以利用头部信息向浏览器发送额外的、结构化的数据。

3. GET请求

GET 是最常见的请求类型,最常用于向服务器查询某些信息。
必要时,可以将查询字符串参数追加到 URL 的末尾,以便将信息发送给服务器。

查询字符串的格式问题:
查询字符串中每个参数的名称和值都必须使用 encodeURIComponent() 进行编码,然后才能放到 URL 的末尾;所有名值对都必须由和号(&)分隔。

向现有 URL 的末尾添加查询字符串参数的辅助函数:

function addURLParam(url, name, value) {
    url += (url.indexOf("?") == -1 ? "?" : "&");
    url += encodeURIComponent(name) + "=" + encodeURIComponent(value);
    return url;
}

一个get请求代码:

var xhr = createXHR(); // var xhr = new XMLHttpRequest()
xhr.onreadystatechange = function(){
    if (xhr.readyState == 4){
        if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
            alert(xhr.responseText);
        } else {
            alert("Request was unsuccessful: " + xhr.status);
        }
    }
};
xhr.open("get", "example.txt", true);
xhr.send(null);

4. POST请求

POST 请求使用频率仅次于 GET,通常用于向服务器发送应该被保存的数据。
不同点:POST 请求应该把数据作为请求的主体提交,GET 请求传统上不是这样。POST 请求的主体可以包含非常多的数据,而且格式不限。

使用 XHR 模仿表单提交:首先将 Content-Type 头部信息设置为 application/x-www-form-urlencoded,也就是表单提交时的内容类型,其次是以适当的格式创建一个字符串(序列化)。

一个post请求代码:

var xhr = createXHR(); // var xhr = new XMLHttpRequest()
xhr.onreadystatechange = function(){
    if (xhr.readyState == 4){
        if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
            alert(xhr.responseText);
        } else {
            alert("Request was unsuccessful: " + xhr.status);
        }
    }
};
xhr.open("post", "postexample.php", true); 
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 
var form = document.getElementById("user-info"); 
xhr.send(serialize(form));

二、XMLHttpRequest 2 级

1. FormData

XMLHttpRequest 2 级定义了 FormData 类型,便于序列化表单以及创建与表单格式相同的数据(用于通过 XHR 传输)。

创建一个 FormData 对象:
var data = new FormData();
通过向 FormData 构造函数中传入表单元素,可以预先填入数据。
var data = new FormData(document.forms[0]);

append():向FormData 对象添加数据。
2个参数:键和值,分别对应表单字段的名字和字段中包含的值。
data.append("name", "Nicholas");

创建了 FormData 的实例后,可以将它直接传给 XHR 的 send() 方法。
var form = document.getElementById("user-info"); xhr.send(new FormData(form));

使用 FormData 的方便之处:不必明确地在 XHR 对象上设置请求头部。XHR 对象能够识别传入的数据类型是 FormData 的实例,并配置适当的头部信息。
支持 FormData 的浏览器:Firefox 4+、Safari 5+、Chrome 和 Android 3+版 WebKit。

2. 超时设定(timeout)

XHR 对象添加了一个 timeout 属性,表示请求在等待响应多少毫秒之后就终止。(IE8+)
在给 timeout 设置一个数值后,如果在规定的时间内浏览器还没有接收到响应,那么就会触发 timeout 事件,进而会调用 ontimeout 事件处理程序。

xhr.open("get", "timeout.php", true);
xhr.timeout = 1000; //将超时设置为1秒钟
xhr.ontimeout = function(){
    alert("Request did not return in a second.");
};
xhr.send(null);

3. overrideMimeType()方法

overrideMimeType():用于重写 XHR 响应的 MIME 类型。(Firefox 最早引入)
注意:调用 overrideMimeType() 必须在 send()方法之前,才能保证重写响应的 MIME 类型。
支持 overrideMimeType() 的浏览器:Firefox、Safari 4+、Opera 10.5 和 Chrome。

使用举例:服务器返回的 MIME 类型是 text/plain,但数据中实际包含的是 XML。根据 MIME 类型,即使数据是 XML,responseXML 属性中仍然是 null。调用 overrideMimeType() 修改 MIME 类型为 text/xml,保证把响应当作 XML 而非纯文本来处理。

三、进度事件

6 个进度事件:

loadstart:在接收到响应数据的第一个字节时触发。
progress:在接收响应期间持续不断地触发。
error:在请求发生错误时触发。
abort:在因为调用 abort() 方法而终止连接时触发。
load:在接收到完整的响应数据时触发。
loadend:在通信完成或者触发 error、abort 或 load 事件后触发。

每个请求都从触发 loadstart 事件开始,接下来是一或多个 progress 事件,然后触发 error、abort 或 load 事件中的一个,最后以触发 loadend 事件结束。

浏览器支持:支持前 5 个事件的浏览器有 Firefox 3.5+、Safari 4+、Chrome、iOS 版 Safari 和 Android 版 WebKit。Opera(从第 11 版开始)、IE 8+只支持 load 事件。目前还没有浏览器支持 loadend 事件。

load事件

load 事件:响应接收完毕后将触发。可以替代 readystatechange 事件,没有必要再检查 readyState 属性。
onload 事件处理程序会接收到一个 event 对象,其 target 属性就指向 XHR 对象实例,因而可以访问到 XHR 对象的所有方法和属性。

progress事件

progress 事件:在浏览器接收新数据期间周期性地触发。
onprogress 事件处理程序会接收到一个 event 对象,其 target 属性是 XHR 对象,但包含着三个额外的属性。
lengthComputable 是一个表示进度信息是否可用的布尔值,position 表示已经接收的字节数,totalSize 表示根据 Content-Length 响应头部确定的预期字节数。

创建进度指示器示例:

var xhr = createXHR(); // var xhr = new XMLHttpRequest()
xhr.onload = function(event){
    if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
        alert(xhr.responseText);
    } else {
        alert("Request was unsuccessful: " + xhr.status);
    }
};
xhr.onprogress = function(event){
    var divStatus = document.getElementById("status");
    if (event.lengthComputable){
    	divStatus.innerHTML = "Received " + event.position + " of " + event.totalSize +" bytes";
    }
};
xhr.open("get", "altevents.php", true);
xhr.send(null);

你可能感兴趣的:(阅读笔记)