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