2005年Jesse James Garrett發(fā)表了一篇文章墨吓,標(biāo)題為:“Ajax:A new Approach to Web Applications”。他在這篇文章里介紹了一種技術(shù)填渠,用他的話說,就叫:Ajax鸟辅,是Asynchronous JavaScript + XML的簡寫氛什。這種技術(shù)能夠想服務(wù)器請求額外的數(shù)據(jù)而無須卸載頁面(即刷新),會帶來更好的用戶體驗匪凉。一時間枪眉,席卷全球。
一.XMLHttpRequest
Ajax技術(shù)核心是XMLHttpRequest對象(簡稱XHR)再层,這是由微軟首先引入的一個特性贸铜,其他瀏覽器提供商后來都提供了相同的實現(xiàn)。在XHR出現(xiàn)之前聂受,Ajax式的通信必須借助一些hack手段來實現(xiàn)蒿秦,大多數(shù)是使用隱藏的框架或內(nèi)嵌框架。
XHR的出現(xiàn)蛋济,提供了向服務(wù)器發(fā)送請求和解析服務(wù)器響應(yīng)提供了流暢的接口棍鳖。能夠以異步方式從服務(wù)器獲取更多的信息,這就意味著碗旅,用戶只要觸發(fā)某一事件鹊杖,在不刷新網(wǎng)頁的情況下,更新服務(wù)器最新的數(shù)據(jù)扛芽。
雖然Ajax中的x代表的是XML骂蓖,但Ajax通信和數(shù)據(jù)格式無關(guān),也就是說這種技術(shù)不一定使用XML川尖。
1.1創(chuàng)建xhr
IE7+登下、Firefox、Opera叮喳、Chrome和Safari都支持原生的XHR對象被芳,在這些瀏覽器中創(chuàng)建XHR對象可以直接實例化XMLHttpRequest即可。
var xhr = new XMLHttpRequest();
alert(xhr); //XMLHttpRequest
1.2open 方法
在使用XHR對象時馍悟,先必須調(diào)用open()方法畔濒,它接受三個參數(shù):要發(fā)送的請求類型(get、post)锣咒、請求的URL和表示是否異步侵状。
xhr.open('get', 'demo.php', false); //對于demo.php的get請求赞弥,false同步
PS:demo.php的代碼如下:
<?php echo Date('Y-m-d H:i:s')?> //一個時間
open()方法并不會真正發(fā)送請求,而只是啟動一個請求以備發(fā)送趣兄。通過send()方法進(jìn)行發(fā)送請求绽左,send()方法接受一個參數(shù),作為請求主體發(fā)送的數(shù)據(jù)艇潭。如果不需要則拼窥,必須填null。執(zhí)行send()方法之后蹋凝,請求就會發(fā)送到服務(wù)器上鲁纠。
xhr.send(null); //發(fā)送請求
1.3 服務(wù)器返回內(nèi)容
當(dāng)請求發(fā)送到服務(wù)器端,收到響應(yīng)后鳍寂,響應(yīng)的數(shù)據(jù)會自動填充XHR對象的屬性房交。那么一共有四個屬性:
屬性名 | 說明 |
---|---|
responseText | 作為響應(yīng)主體被返回的文本 |
responseXML | 如果響應(yīng)主體內(nèi)容類型是"text/xml"或"application/xml",則返回包含響應(yīng)數(shù)據(jù)的XML DOM文檔 |
status | 響應(yīng)的HTTP狀態(tài) |
statusText | HTTP狀態(tài)的說明 |
接受響應(yīng)之后伐割,第一步檢查status屬性候味,以確定響應(yīng)已經(jīng)成功返回。一般而已HTTP狀態(tài)代碼為200作為成功的標(biāo)志隔心。除了成功的狀態(tài)代碼白群,還有一些別的:
1.4 http狀態(tài)碼
HTTP狀態(tài)碼 | 狀態(tài)字符串 | 說明 |
---|---|---|
200 | OK | 服務(wù)器成功返回了頁面 |
300 | 跳轉(zhuǎn) | 重定向地址 |
400 | Bad Request | 語法錯誤導(dǎo)致服務(wù)器不識別 |
401 | Unauthorized | 請求需要用戶認(rèn)證 |
404 | Not found | 指定的URL在服務(wù)器上找不到 |
500 | Internal Server Error | 服務(wù)器遇到意外錯誤,無法完成請求 |
503 | ServiceUnavailable | 由于服務(wù)器過載或維護(hù)導(dǎo)致無法完成請求 |
http://tool.oschina.net/commons?type=5 http響應(yīng)碼 全解
我們判斷HTTP狀態(tài)值即可硬霍,不建議使用HTTP狀態(tài)說明帜慢,因為在跨瀏覽器的時候,可能會不太一致唯卖。
addEvent(document, 'click', function () {
var xhr = new XMLHttpRequest();
xhr.open('get', 'demo.php?rand=' + Math.random(), false); //設(shè)置了同步
xhr.send(null);
if (xhr.status == 200) { //如果返回成功了
alert(xhr.responseText); //調(diào)出服務(wù)器返回的數(shù)據(jù)
} else {
alert('數(shù)據(jù)返回失斄涣帷!狀態(tài)代碼:' + xhr.status + '狀態(tài)信息:' + xhr.statusText);
}
});
以上的代碼每次點擊頁面的時候拜轨,返回的時間都是時時的抽减,不同的,說明都是通過服務(wù)器及時加載回的數(shù)據(jù)橄碾。
1.5 readystatechange(狀態(tài)發(fā)生改變)
使用異步調(diào)用的時候卵沉,需要觸發(fā)readystatechange事件,然后檢測readyState屬性即可法牲。這個屬性有五個值:
值 | 狀態(tài) | 說明 |
---|---|---|
0 | 未初始化 | 尚未調(diào)用open()方法 |
1 | 啟動 已經(jīng)調(diào)用open()方法史汗, | 但尚未調(diào)用send()方法 |
2 | 發(fā)送 已經(jīng)調(diào)用send()方法, | 但尚未接受響應(yīng) |
3 | 接受 | 已經(jīng)接受到部分響應(yīng)數(shù)據(jù) |
4 | 完成 已經(jīng)接受到全部響應(yīng)數(shù)據(jù)拒垃, | 而且可以使用 |
addEvent(document, 'click', function () {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
alert(xhr.responseText);
} else {
alert('數(shù)據(jù)返回失斖W病!狀態(tài)代碼:' + xhr.status + '狀態(tài)信息:'
- xhr.statusText);
}
}
};
xhr.open('get', 'demo.php?rand=' + Math.random(), true);
xhr.send(null);
});
PS:使用abort()方法可以取消異步請求悼瓮,放在send()方法之前會報錯戈毒。放在responseText之前會得到一個空值艰猬。
二.GET與POST
在提供服務(wù)器請求的過程中,有兩種方式副硅,分別是:GET和POST姥宝。在Ajax使用的過程中翅萤,GET的使用頻率要比POST高恐疲。
2.1 GET請求
GET請求是最常見的請求類型,最常用于向服務(wù)器查詢某些信息套么。必要時培己,可以將查詢字符串參數(shù)追加到URL的末尾,以便提交給服務(wù)器胚泌。
xhr.open('get', 'demo.php?rand=' + Math.random() + '&name=Koo', true);
通過URL后的問號給服務(wù)器傳遞鍵值對數(shù)據(jù)省咨,服務(wù)器接收到返回響應(yīng)數(shù)據(jù)。特殊字符傳參產(chǎn)生的問題可以使用encodeURIComponent()進(jìn)行編碼處理玷室,中文字符的返回及傳參零蓉,可以講頁面保存和設(shè)置為utf-8格式即可。
//一個通用的URL提交函數(shù)
function addURLParam(url, name, value) {
url += (url.indexOf('?') == -1 ? '?' : '&'); //判斷的url是否有已有參數(shù)
url += encodeURIComponent(name) + '=' + encodeURIComponent(value);
alert(url);
return url;
}
PS:當(dāng)沒有encodeURIComponent()方法時穷缤,在一些特殊字符比如“&”敌蜂,會出現(xiàn)錯誤導(dǎo)致無法獲取。
2.2 POST請求
POST請求可以包含非常多的數(shù)據(jù)津肛,我們在使用表單提交的時候章喉,很多就是使用的POST傳輸方式。
xhr.open('post', 'demo.php', true);
而發(fā)送POST請求的數(shù)據(jù)身坐,不會跟在URL的尾巴上秸脱,而是通過send()方法向服務(wù)器提交數(shù)據(jù)。
xhr.send('name=Lee&age=100');
一般來說部蛇,向服務(wù)器發(fā)送POST請求由于解析機(jī)制的原因摊唇,需要進(jìn)行特別的處理。因為POST請求和Web表單提交是不同的涯鲁,需要使用XHR來模仿表單提交遏片。
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
PS:從性能上來講POST請求比GET請求消耗更多一些,用相同數(shù)據(jù)比較撮竿,GET最多比POST快兩倍吮便。
2.3 用json來解析服務(wù)器數(shù)據(jù)
上一節(jié)課的JSON也可以使用Ajax來回調(diào)訪問。
var url = 'demo.json?rand=' + Math.random();
var box = JSON.parse(xhr.responseText);