XMLHTTPRequest屬性、方法、事件整理大全。
xhr 對象的方法
-
open(method:string, url:string, async?:boolean=true, username?:string, password: string)- 用於創建
HTTP請求,但請求並未發送。 method, 請求類型,如GET、POST等,大小寫不敏感。url,URL地址-
async, 是否異步,默認true。
若為同步請求時xhr.timeout值必須為 0。xhr.withCredentials值必須為 false。xhr.responseType值必須為"",(text也不允許)。
username, 用户名,一般不用。password, 密碼,一般不用。
- 用於創建
-
send(body?:Object=null)-
定義
HTTP請求的數據(body),當method為GET、HEAD時,該參數忽略。body可為ArrayBuffer、Blob、Document(類似XML格式數據)、DOMString(字符串)、FormData(表單)。
ArrayBuffer、Blob、Document、DOMString、Formdata 詳細參考。
注意:body 參數會影響請求頭部的content-type默認值。- 如果
data是Document類型,同時也是HTML Document類型,則content-type默認值為text/html;charset=UTF-8;否則為application/xml;charset=UTF-8; - 如果
data是DOMString類型,content-type默認值為text/plain;charset=UTF-8; - 如果
data是FormData類型,content-type默認值為multipart/form-data; boundary=[xxx] -
如果
data是其他類型,則不會設置content-type的默認值如果用 xhr.setRequestHeader()手動設置了中 content-type 的值,以上默認值就會被覆蓋。
若在斷網狀態下調用 xhr.send(data)方法,則會拋錯:Uncaught NetworkError: Failed to execute 'send' on 'XMLHttpRequest'。一旦程序拋出錯誤,如果不 catch 就無法繼續執行後面的代碼,所以調用 xhr.send(data)方法時,應該用 try-catch 捕捉錯誤。
try{ xhr.send(data) }catch(e) { //doSomething... }; - 如果
-
-
abort()- 若請求已發出,則會終止請求,並將 readyState 置為 0.
- 調用後,應將 xhr 對象置為 null 以促進垃圾回收。由於內存原因,不建議重用 xhr 對象。
擴展閲讀:和瀏覽器異步請求取消相關的那些事
overrideMimeType(type:string)
重寫 response 的 content-type。功能如同 xhr.responseType,已可以摒棄。-
setRequestHeader(header:string, value:string)- 設置請求 HTTP 請求頭信息。如
content-type、cookie、accept-xxx等。 - header 參數大小寫不敏感。
- 必須在
open()方法後,send()方法前調用,否則會拋錯。 - 可調用多次,最終值不會覆蓋,而是採用追加
append方式。 -
禁止設置以下請求頭,否則會拋錯。
Accept-CharsetAccept-EncodingAccess-Control-Request-HeadersAccess-Control-Request-MethodConnectionContent-LengthCookieCookie2DateDNTExpectHostKeep-AliveOriginRefererTETrailerTransfer-EncodingUpgradeUser-AgentVia
- 設置請求 HTTP 請求頭信息。如
-
getResponseHeader(header:string)- 獲取某個指定 header 字段的值。
- header 字段不區分大小寫。
- 有嚴格安全限制,詳見
getAllResponseHeaders方法。
-
getAllResponseHeaders()- 獲取 response 中所有 header 字段。
-
有嚴格安全限制。如下:
- 無論跨域或同域請求,無法獲取
Set-Cookie、Set-Cookie2字段值。 -
跨域請求,只可獲取simple response header和Access-Control-Expose-Headers(名詞解釋見下方),否則會報錯:
Refused to get unsafe header。故若想訪問其他字段,需後端添加到Access-Control-Expose-Headers中。simple response header包括的header字段有:Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma。
- 無論跨域或同域請求,無法獲取
> `Access-Control-Expose-Headers`:跨域請求獨有,同域請求無。該字段中列舉的 `header` 字段為服務器允許暴露給客户端訪問的字段。
> 句法:```Access-Control-Expose-Headers: <header-name>, <header-name>, ...```
xhr 的屬性
-
readyState
[只讀屬性]用於追蹤xhr當前的狀態,共有 5 種可能的值,分別對應xhr不同的階段。
每次readyState值變化時,都會觸發xhr.onreadystatechange事件。值 狀態 描述 0UNSENT(初始狀態,未打開)此時 xhr對象被成功構造,open()方法還未被調用1OPENED(已打開,未發送)open()方法已被成功調用,send()方法還未被調用。注意:只有xhr處於OPENED狀態,才能調用xhr.setRequestHeader()和xhr.send(),否則會報錯2HEADERS_RECEIVED(已獲取響應頭)send()方法已經被調用, 響應頭和響應狀態已經返回3LOADING(正在下載響應體)響應體( response entity body)正在下載中,此狀態下xhr.response可能已經有了響應數據4DONE(整個數據傳輸過程結束)整個數據傳輸過程結束,不管本次請求是成功還是失敗 -
status和statusText
status屬性表示HTTP響應狀態碼,如200、302、400等。
statusText屬性表示HTTP響應狀態的描述文本,如OK、Not Found等。
注意,在xhr.onload事件中,不能簡單的判斷xhr.status === 200,因為20x、304等HTTP狀態碼也被認為是請求成功。
參考以下代碼:xhr.onload = function () { //如果請求成功 if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ //do successCallback } } -
responseType和response
可在xhr.send()前設置responseType,用於指定返回的響應數據類型。和xhr.overrideMimeType()方法效果相同,推薦使用responseType。- IE10/IE11 不支持
xhr.responseType為json。 -
部分瀏覽器不支持
xhr.responseType為blob。值 描述 ""將 responseType設為空字符串與設置為text相同, 是默認類型 (實際上是DOMString)。arraybufferresponse是一個包含二進制數據的JavaScript ArrayBuffer。blobresponse是一個包含二進制數據的Blob對象 。documentresponse是一個HTML Document或XML XMLDocument,這取決於接收到的數據的MIME類型。使用XHR獲取HTML請參閲HTML in XMLHttpRequest。jsonresponse是一個JavaScript對象。這個對象是通過將接收到的數據類型視為JSON解析得到的。textresponse是包含在DOMString對象中的文本。moz-chunked-arraybuffer與 arraybuffer相似,但是數據會被接收到一個流中。使用此響應類型時,響應中的值僅在progress事件的處理程序中可用,並且只包含上一次響應progress事件以後收到的數據,而不是自請求發送以來收到的所有數據。在progress事件處理時訪問response將返回到目前為止收到的數據。在progress事件處理程序之外訪問,response的值會始終為null。ms-streamresponse是下載流的一部分;此響應類型僅允許下載請求,僅IE支持。
- IE10/IE11 不支持
-
responseText- 默認值為空字符串
"" - 只有當
responseType為text、""時,xhr對象上才有此屬性,此時才能調用xhr.responseText,否則拋錯。 - 只有當請求成功時,才能拿到正確值。以下
2種情況下值都為空字符串"":請求未完成、請求失敗。
- 默認值為空字符串
-
responseXML- 默認值為
null - 只有當
responseType為text、""、document時,xhr對象上才有此屬性,此時才能調用xhr.responseXML,否則拋錯。 - 只有當請求成功且返回數據被正確解析時,才能拿到正確值。以下
3種情況下值都為null:請求未完成、請求失敗、請求成功但返回數據無法被正確解析時。
- 默認值為
-
upload-
是一個
XMLHttpRequestUpload對象,用於收集傳輸信息。支持事件:onloadstartonprogressonabortontimeoutonerroronloadonloadend
具體觸發順序及條件,參考事件章節。
其中,xhr.upload.onprogress在上傳階段(即xhr.send()之後,xhr.readystate=2之前)觸發,每 50ms 觸發一次。可獲得上傳信息、進度等。
上述事件回調的參數為XMLHttpRequestEventTarget對象,詳見 事件補充。
-
-
timeout- 單位毫秒,默認值
0,即不設置超時。 - 計時從
onloadstart事件觸發開始(即xhr.send()開始),以onloadend事件觸發為結束。 - 在 IE 中,只能在調用
open()方法後send()方法前設置。其他瀏覽器無此限制,但仍然從xhr.send()方法調用計時。 - 不能為同步請求設置
timeout,否則會報錯。 - 早期較多瀏覽器不支持,可通過
setTImeOut實現。
- 單位毫秒,默認值
-
withCredentials
boolean類型,默認值false, 用於跨域請求時將cookie加入到request header。xhr.withCredentials與CORS什麼關係
我們都知道,在發同域請求時,瀏覽器會將cookie自動加在request header中。但在發送跨域請求時,cookie並不會自動加在request header中。
造成這個問題的原因:在CORS標準有如下規定,默認情況下,瀏覽器在發送跨域請求時,不能發送任何認證信息(credentials)如cookies和HTTP authentication schemes。除非xhr.withCredentials為true。
cookies也是一種認證信息,在跨域請求中,client端必須手動設置xhr.withCredentials=true,且server端也必須允許request能攜帶認證信息(即response header中包含Access-Control-Allow-Credentials:true),這樣瀏覽器才會自動將cookie加在request header中。
注意,一旦跨域request能夠攜帶認證信息,server端一定不能將Access-Control-Allow-Origin設置為*,而必須設置為請求頁面的域名。
xhr 的事件回調
xhr 共有 8 個事件,分別如下:
onloadstartonprogressonabortontimeoutonerroronloadonloadendonreadystatechange
事件觸發條件
引用自 你真的會使用 XMLHttpRequest 嗎?
| 事件 | 觸發條件 |
|---|---|
onreadystatechange |
每當xhr.readyState改變時觸發;但xhr.readyState由非 0 值變為 0 時不觸發。 |
onloadstart |
調用xhr.send()方法後立即觸發,若xhr.send()未被調用則不會觸發此事件。 |
onprogress |
xhr.upload.onprogress在上傳階段(即xhr.send()之後,xhr.readystate=2之前)觸發,每 50ms 觸發一次;xhr.onprogress在下載階段(即xhr.readystate=3時)觸發,每 50ms 觸發一次。 |
onload |
當請求成功完成時觸發,此時xhr.readystate=4 |
onloadend |
當請求結束(包括請求成功和請求失敗)時觸發 |
onabort |
當調用xhr.abort()後觸發 |
ontimeout |
xhr.timeout不等於 0 ,由請求開始即 onloadstart 開始算起,當到達xhr.timeout 所設置時間請求還未結束即 onloadend ,則觸發此事件。 |
onerror |
在請求過程中,若發生 Network error 則會觸發此事件(若發生 Network error 時,上傳還沒有結束,則會先觸發 xhr.upload.onerror,再觸發 xhr.onerror ;若發生 Network error 時,上傳已經結束,則只會觸發xhr.onerror )。注意,只有發生了網絡層級別的異常才會觸發此事件,對於應用層級別的異常,如響應返回的xhr.statusCode是 4xx 時,並不屬於 Network error ,所以不會觸發 onerror 事件,而是會觸發 onload 事件。 |
請求正常時,事件觸發順序
- 觸發
xhr.onreadystatechange(之後每次 readyState 變化時,都會觸發一次) - 觸發
xhr.onloadstart//上傳階段開始: - 觸發
xhr.upload.onloadstart - 觸發
xhr.upload.onprogress - 觸發
xhr.upload.onload - 觸發
xhr.upload.onloadend//上傳結束,下載階段開始: - 觸發
xhr.onprogress - 觸發
xhr.onload - 觸發
xhr.onloadend
發生 abort / timeout / error 時事件觸發順序
- 觸發
xhr.onreadystatechange事件,此時readystate為4 -
如果上傳階段還沒有結束,則依次觸發以下事件:
xhr.upload.onprogressxhr.upload.[onabort或ontimeout或onerror]xhr.upload.onloadend
- 觸發
xhr.onprogress事件 - 觸發
xhr.[onabort或ontimeout或onerror]事件 - 觸發
xhr.onloadend事件
事件補充
xhr.upload.onprogress 和 xhr.onprogress 的回調參數為 XMLHttpRequestEventTarget 對象。屬性如下:
lengthComputable
【只讀】,為boolean值,表示資源是否有可計算的長度。loaded
已接收或已上傳的字節數。total
文件總字節數。xhr.upload.onprogress事件觸發於上傳階段,可用於獲取上傳進度。xhr.onprogress事件觸發於下載階段,可用於獲取下載進度。
後續補充計劃
fetchAPI整理。jQuery.ajax的實現詳解。axios的實現詳解。
參考資料
- DOMString、Document、FormData、Blob、File、ArrayBuffer 數據類型介紹
- 你真的會使用
XMLHttpRequest嗎? - XMLHttpRequest Level 2 使用指南