Ajax與XMLHttpRequest

Ajax和XMLHttpRequest

Ajax:"Asynchronous JavaScript And XML"即異步JavaScript和XML,是一種創(chuàng)建交互式網(wǎng)頁應(yīng)用的網(wǎng)頁開發(fā)技術(shù),這項(xiàng)技術(shù)的核心是瀏覽器提供的XMLHttpRequest對象。

XMLHttpRequest的使用

1.設(shè)置request header

void setRequestHeader(headerName, headerValue)

  • setRequestHeader必須寫在open()方法之后,send()方法之前

2. 獲取response header

getAllResponseHeaders()

  • 獲取全部可獲?。ㄓ幸恍﹉eader是獲取不到的)的header字段

getResponseHeader(headerName)

  • 獲取指定header字段的值(只能獲取部分header的值)

3. 指定xhr.response的數(shù)據(jù)類型

  • 通過設(shè)置xhr.response的類型,是告訴瀏覽器或者xhr如何處理響應(yīng)數(shù)據(jù)(對響應(yīng)數(shù)據(jù)按照什么樣的格式去處理)

xhr.overrideMimeType()

  • 這個(gè)方法的作用就是重寫response的MIME類型
  • 這個(gè)方法必須在send()方法之前進(jìn)行調(diào)用
  • 可以通過這種方式,可以得到純文本格式的圖片內(nèi)容,獲取到數(shù)據(jù)后再使用相應(yīng)的編碼方法重新構(gòu)建圖片

var xhr = new XMLHtppRequest()
xhr.open('get', 'text.php', true)
xhr.overrideMimeType("text/xml; charset=utf-8")
xhr.send();

根據(jù)上面的例子,將response的MIME類型設(shè)置為了'text/xml',通過這樣的方式,xhr會將響應(yīng)當(dāng)做text或者xml來處理,通過xhr.responsexhr.responseText可以獲取到文本格式的相應(yīng)數(shù)據(jù),通過xhr.responseXML可以獲取到XML格式(是一顆DOM樹/DOM對象)的數(shù)據(jù)


var xhr = new XMLHtppRequest()
xhr.open('get', 'text.php', true)
xhr.overrideMimeType("text/plain; charset=utf-8")
xhr.send();

根據(jù)上面的例子,將response的MIME類型設(shè)置為了'text/plain',通過這樣的方式,xhr會將相應(yīng)當(dāng)做text或者plain(純文本)來處理,通過xhr.responsexhr.responseText可以獲取到文本格式的相應(yīng)數(shù)據(jù),通過xhr.responseXML獲取到的數(shù)據(jù)為null,即便數(shù)據(jù)是XML


xhr.responseType

responseType是XMLHttpRequest leve2中新增的屬性,用來指定xhr.response的數(shù)據(jù)類型

responseType
var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png', true);
//可以將`xhr.responseType`設(shè)置為`"blob"`也可以設(shè)置為`" arrayBuffer"`
//xhr.responseType = 'arrayBuffer';
xhr.responseType = 'blob';

xhr.onload = function(e) {
  if (this.status == 200) {
    // this.response就是Blob對象
    var blob = this.response;
    ...
  }
};

xhr.send();

4. 如何獲取response數(shù)據(jù)

xhr提供了3個(gè)屬性來獲取請求返回的數(shù)據(jù),分別是:xhr.response, xhr.responseText, xhr.responseXML

  • xhr.response:

    • 無論xhr.responseType的值是什么,只要請求完成,都可以從xhr.response中取到對應(yīng)的值
    • 請求未完成時(shí),xhr.response的值與xhr.responseType有關(guān),xhr.responseType的值為""(默認(rèn)值)或者text時(shí),xhr.response的值為"",否則為null
  • xhr.responseText:

    • 只有當(dāng)responseType設(shè)置為''或者text時(shí),才可以使用這個(gè)屬性獲取相應(yīng)內(nèi)容
    • 請求未完成、失敗時(shí),該值為空字符串
  • xhr.responseXML:

    • 只有當(dāng) responseType 為''、document時(shí),此時(shí)才能調(diào)用xhr.responseXML,否則拋錯(cuò)
    • 請求未完成、失敗時(shí),該值為null

5. 如何追蹤ajax請求的當(dāng)前狀態(tài)

  • xhr.readyState屬性可以獲取ajax的狀態(tài),每當(dāng)xhr.readyState的值發(fā)生變化時(shí),就會觸發(fā)xhr.onreadystatechange事件,可以在這個(gè)事件中進(jìn)行相應(yīng)的操作
  • 為了保證跨瀏覽器兼容性,必須在調(diào)用open()方法之前指定onreadystatechange事件處理程序
 xhr.onreadystatechange = function () {
    switch(xhr.readyState){
      case 1://OPENED
        //do something
            break;
      case 2://HEADERS_RECEIVED
        //do something
        break;
      case 3://LOADING
        //do something
        break;
      case 4://DONE
        //do something
         break;
    }
xhr.readyState

6 設(shè)置請求的超時(shí)時(shí)間

  • XMLHttpRequest提供了timeout屬性來允許設(shè)置請求的超時(shí)時(shí)間。
  • 從請求開始 算起,若超過 timeout 時(shí)間請求還沒有結(jié)束(包括成功/失?。?,則會觸發(fā)ontimeout事件,主動結(jié)束該請求。
  • 請求開始:xhr.onloadstart事件觸發(fā)的時(shí)候,也就是你調(diào)用xhr.send()方法的時(shí)候
  • 請求結(jié)束:xhr.loadend事件觸發(fā)的時(shí)候。

7 發(fā)送同步請求

  • 由open()方法的第三個(gè)參數(shù)決定,當(dāng)?shù)谌齻€(gè)參數(shù)async為true時(shí),發(fā)送異步請求,為false時(shí)則為同步請求

  • 當(dāng)xhr為同步請求時(shí),有如下限制:

    • xhr.timeout必須為0
    • xhr.withCredentials必須為 false
    • xhr.responseType必須為""(即默認(rèn)值)
  • 避免使用同步請求:因?yàn)槲覀儫o法設(shè)置請求超時(shí)時(shí)間(xhr.timeout為0,即不限時(shí))。在不限制超時(shí)的情況下,有可能同步請求一直處于pending狀態(tài),服務(wù)端遲遲不返回響應(yīng),這樣整個(gè)頁面就會一直阻塞,無法響應(yīng)用戶的其他交互。

8 如何獲取上傳、下載進(jìn)度

我們可以通過onprogress事件來實(shí)時(shí)顯示進(jìn)度,默認(rèn)情況下這個(gè)事件每50ms觸發(fā)一次。需要注意的是,上傳過程和下載過程觸發(fā)的是不同對象的onprogress事件:

  • 上傳觸發(fā)的是xhr.upload對象的 onprogress事件
  • 下載觸發(fā)的是xhr對象的onprogress事件
xhr.onprogress = updateProgress;
xhr.upload.onprogress = updateProgress;
function updateProgress(event) {
    if (event.lengthComputable) {
      var completedPercent = event.loaded / event.total;
    }
 }

xhr相關(guān)事件

xhr相關(guān)事件

每一XMLHttpRequest對象都有一個(gè)upload屬性,而upload是一個(gè)XMLHttpRequestUpload對象.XMLHttpRequest和XMLHttpRequestUpload對象共同擁有上述(除onreadystatechange事件)事件。onreadystatechange是XMLHttpRequest對象獨(dú)有的事件

事件觸發(fā)順序

  1. 觸發(fā)xhr.onreadystatechange(之后每次readyState變化時(shí),都會觸發(fā)一次)
  2. 觸發(fā)xhr.onloadstart

上傳階段開始:

  1. 觸發(fā)xhr.upload.onloadstart
  2. 觸發(fā)xhr.upload.onprogress
  3. 觸發(fā)xhr.upload.onload
  4. 觸發(fā)xhr.upload.onloadend

上傳結(jié)束,下載階段開始:

  1. 觸發(fā)xhr.onprogress
  2. 觸發(fā)xhr.onload
  3. 觸發(fā)xhr.onloadend

發(fā)生abort/timeout/error異常的處理

  1. 一旦發(fā)生abort或timeout或error異常,先立即中止當(dāng)前請求
  2. 將 readystate 置為4,并觸發(fā) xhr.onreadystatechange事件
  3. 如果上傳階段還沒有結(jié)束,則依次觸發(fā)以下事件:
    • xhr.upload.onprogress
    • xhr.upload.[onabort或ontimeout或onerror]
    • xhr.upload.onloadend
    • 注意不會觸發(fā)onloadstart和onload事件
  4. 觸發(fā) xhr.onprogress事件
  5. 觸發(fā) xhr.[onabort或ontimeout或onerror]事件
  6. 觸發(fā)xhr.onloadend 事件
  7. 注意不會觸發(fā)onloadstart和onload事件
  • 注意: 這時(shí)候的xhr.readyState為4,xhr.status為0

在哪個(gè)事件中注冊成功回調(diào)

從上面介紹的事件中,可以知道若xhr請求成功,就會觸發(fā)xhr.onreadystatechange和xhr.onload兩個(gè)事件。由于xhr.onreadystatechange是每次xhr.readyState變化時(shí)都會觸發(fā),而不是xhr.readyState=4時(shí)才觸發(fā)(例如發(fā)生abort、timeout、error異常,會先終止當(dāng)前請求,將readyState設(shè)置為4,并觸發(fā)onreadystatechange事件),因此建議在onload事件中注冊成功回調(diào)

xhr.onload = function () {
    //如果請求成功
    if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
      //do successCallback
    }
  }
為什么要對xhr.status進(jìn)行上述判斷

xhr.status代表相應(yīng)的HTTP狀態(tài)
以2開頭的狀態(tài)碼,代表請求已經(jīng)成功被服務(wù)器接收、理解、并接受
狀態(tài)代碼304代表請求的資源并沒有修改,可以直接使用瀏覽器中緩存的版本
其他以3開頭的狀態(tài)代碼則表示需要客戶端采取進(jìn)一步的操作才能完成請求。

status和readyState
  • status是響應(yīng)的HTTP狀態(tài),statusText是HTTP狀態(tài)的說明
  • readyState是表示在請求/響應(yīng)過程中的當(dāng)前活動處于哪個(gè)階段

你真的會使用XMLHttpRequest嗎?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Ajax和XMLHttpRequest 我們通常將Ajax等同于XMLHttpRequest,但細(xì)究起來它們兩個(gè)是...
    changxiaonan閱讀 2,391評論 0 2
  • 看到標(biāo)題時(shí),有些同學(xué)可能會想:“我已經(jīng)用xhr成功地發(fā)過很多個(gè)Ajax請求了,對它的基本操作已經(jīng)算挺熟練了。” 我...
    前端渣渣閱讀 6,056評論 1 12
  • 本文詳細(xì)介紹了 XMLHttpRequest 相關(guān)知識,涉及內(nèi)容: AJAX、XMLHTTP、XMLHttpReq...
    semlinker閱讀 13,999評論 2 18
  • AJAX 原生js操作ajax 1.創(chuàng)建XMLHttpRequest對象 var xhr = new XMLHtt...
    碧玉含香閱讀 3,574評論 0 7
  • ajax作為前端開發(fā)必需的基礎(chǔ)能力之一,你可能會使用它,但并不一定懂得其原理,以及更深入的服務(wù)器通信相關(guān)的知識。在...
    蕭玄辭閱讀 887評論 0 0

友情鏈接更多精彩內(nèi)容