AJAX是Asynchronous JavasSript And XML的簡(jiǎn)寫,這項(xiàng)技術(shù)能夠在不卸載頁(yè)面的情況下發(fā)出HTTP請(qǐng)求,雖然名字中包含XML,但AJAX通信與數(shù)據(jù)格式無關(guān)
AJAX通信通常包含4個(gè)步驟:
- 創(chuàng)建XMLHttpRequest對(duì)象
- 發(fā)送HTTP請(qǐng)求
- 接收服務(wù)器返回的數(shù)據(jù)
- 更新網(wǎng)頁(yè)數(shù)據(jù)
創(chuàng)建
AJAX技術(shù)的核心是XMLHttpRequest對(duì)象(簡(jiǎn)稱XHR),可以直接使用new關(guān)鍵字實(shí)例化一個(gè)XHR對(duì)象
var xhr = new XMLHttpRequest()
注意: 如果要建立N個(gè)不同的請(qǐng)求,理論上需要使用N個(gè)不同的XHR對(duì)象。如果重用已存在的XHR對(duì)象,會(huì)終止之前通過該對(duì)象掛起的任何請(qǐng)求
發(fā)送請(qǐng)求
open()
XHR對(duì)象的open()方法用于發(fā)送請(qǐng)求,該方法接收三個(gè)參數(shù):請(qǐng)求方式、請(qǐng)求地址和一個(gè)布爾值
xhr.open("GET","/api/test", true);
請(qǐng)求方式:請(qǐng)求方式比較常用的是GET和POST,也可以是PATCH、DELETE、OPTIONS等。這個(gè)字符串是不區(qū)分大小寫的,但通常使用大寫字母。
請(qǐng)求地址:請(qǐng)求地址通常是相對(duì)于執(zhí)行代碼的當(dāng)前頁(yè)面。如果需要發(fā)出跨域請(qǐng)求,后端要支持CORS,否則會(huì)報(bào)錯(cuò)
布爾值:布爾值表示是否異步發(fā)送請(qǐng)求的布爾值,默認(rèn)為true,表示異步發(fā)送
其他:如果請(qǐng)求一個(gè)受密碼保護(hù)的URL,可以把用于認(rèn)證的用戶名和密碼作為第4和第5個(gè)參數(shù)傳遞給open()方法
send()
open()方法調(diào)用后,必須執(zhí)行send()方法才會(huì)真正發(fā)送請(qǐng)求。如果是GET方式,send()方法無參數(shù),或參數(shù)為null;如果是POST方式,send()方法的參數(shù)為要發(fā)送的數(shù)據(jù)
xhr.open('GET', 'https://www.86886.wang/api/tags', true);
xhr.send(null);
接收響應(yīng)
一個(gè)完整的HTTP請(qǐng)求由響應(yīng)狀態(tài)碼、響應(yīng)頭集合和響應(yīng)主體組成。在收到響應(yīng)后,這些都可以通過XHR對(duì)象的屬性和方法使用,主要有以下4個(gè)屬性
responseText: 作為響應(yīng)主體被返回的文本(文本形式)
responseXML: 如果響應(yīng)的內(nèi)容類型是'text/xml'或'application/xml',這個(gè)屬性中將保存著響應(yīng)數(shù)據(jù)的XML DOM文檔(document形式)
status: HTTP狀態(tài)碼(數(shù)字形式),比如200
statusText: HTTP狀態(tài)說明(文本形式),比如OK
在接收到響應(yīng)后,第一步是檢測(cè)status狀態(tài),HTTP狀態(tài)碼為200表示請(qǐng)求成功,此時(shí)responseText屬性的內(nèi)容已經(jīng)就緒。另外狀態(tài)碼304表示資源沒有被修改,可以直接從瀏覽器緩存獲取,這個(gè)響應(yīng)也是有效的
無論內(nèi)容類型是什么,響應(yīng)主體的內(nèi)容都會(huì)保存到responseText屬性中。對(duì)于非XML數(shù)據(jù)而言(如JSON),responseXML屬性的值將為null
if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
console.log(xhr.responseText);
}else{
console.log('Request fail:' + xhr.status);
}
同步請(qǐng)求
把open()方法的第三個(gè)參數(shù)設(shè)置為false,表示是同步請(qǐng)求,此時(shí)send()方法將會(huì)阻塞直到請(qǐng)求完成。由于JS是單線程的,所以會(huì)導(dǎo)致整個(gè)瀏覽器UI凍結(jié),如果連接的服務(wù)器響應(yīng)慢,那么用戶的瀏覽器將凍結(jié)
開發(fā)中要避免使用同步請(qǐng)求,下面是同步請(qǐng)求的示例
<div id="result"></div>
<button id="btn">GET同步請(qǐng)求</button>
<script>
btn.onclick = function() {
var data = ajax();
result.innerHTML = data;
}
function ajax() {
var xhr = new XMLHttpRequest();
if(xhr.readyState == 4) {
if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
return xhr.responseText;
}
}
// 同步請(qǐng)求
xhr.open('GET', 'https://www.86886.wang/api/tags', false);
xhr.send();
}
</script>
異步請(qǐng)求
異步請(qǐng)求需要檢測(cè)XHR對(duì)象的readyState屬性,該屬性表示請(qǐng)求/響應(yīng)過程的當(dāng)前活動(dòng)階段,取值如下:
0(UNSENT):未初始化。尚未調(diào)用open()方法
1(OPENED):啟動(dòng)。已經(jīng)調(diào)用open()方法,但尚未調(diào)用send()方法
2(HEADERS_RECEIVED):發(fā)送。己經(jīng)調(diào)用send()方法,且接收到頭信息
3(LOADING):接收。已經(jīng)接收到部分響應(yīng)主體信息
4(DONE):完成。已經(jīng)接收到全部響應(yīng)數(shù)據(jù),而且已經(jīng)可以在客戶端使用了
只要readyState屬性值發(fā)生變化,就會(huì)觸發(fā)onreadystatechange事件,通常只需要對(duì)值為4時(shí)做判斷,此時(shí)表示數(shù)據(jù)已經(jīng)準(zhǔn)備就緒
注意: 必須在調(diào)用open()之前指定onreadystatechange 事件處理程序才能確??鐬g覽器兼容性,否則將無法接收readyState屬性為0和1的情況
異步請(qǐng)求示例
<div id="result"></div>
<button id="btn">GET異步請(qǐng)求</button>
<script>
btn.onclick = function() {
ajax(function(data) {
result.innerHTML = data;
});
}
function ajax(cb) {
var xhr = new XMLHttpRequest();
// 異步請(qǐng)求
xhr.onreadystatechange = function() {
if(xhr.readyState == 4) {
if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
cb(xhr.responseText);
}
}
}
xhr.open('GET', 'https://www.86886.wang/api/tags', true);
xhr.send();
}
</script>
超時(shí)
XHR對(duì)象有一個(gè)timeout屬性,表示多少毫秒后,如果請(qǐng)求仍然沒有得到結(jié)果就會(huì)自動(dòng)終止。默認(rèn)值0,表示沒有限制
如果請(qǐng)求超時(shí),會(huì)觸發(fā)ontimeout事件
function ajax(cb) {
var xhr = new XMLHttpRequest();
// 異步請(qǐng)求
xhr.onreadystatechange = function() {
if(xhr.readyState == 4) {
if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
cb(xhr.responseText);
}
}
}
xhr.open('GET', 'https://www.86886.wang/api/tags', true);
xhr.ontimeout = function() {
console.log('The request timed out.');
}
xhr.timeout = 5000; // 5s
xhr.send();
}
本文摘自 :https://www.cnblogs.com/