當(dāng)前位置:首頁(yè) > IT技術(shù) > Web編程 > 正文

JS之AJAX-XHR對(duì)象
2021-09-29 14:49:43

AJAX是Asynchronous JavasSript And XML的簡(jiǎn)寫,這項(xiàng)技術(shù)能夠在不卸載頁(yè)面的情況下發(fā)出HTTP請(qǐng)求,雖然名字中包含XML,但AJAX通信與數(shù)據(jù)格式無關(guān)

AJAX通信通常包含4個(gè)步驟:

  1. 創(chuàng)建XMLHttpRequest對(duì)象
  2. 發(fā)送HTTP請(qǐng)求
  3. 接收服務(wù)器返回的數(shù)據(jù)
  4. 更新網(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/

開通會(huì)員,享受整站包年服務(wù)立即開通 >