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

JS之AJAX-XHR對象
2021-09-29 14:49:43

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

AJAX通信通常包含4個步驟:

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

開通會員,享受整站包年服務立即開通 >