XMLHttpRequest物件詳解
XMLHttpRequest提供了一組用於客戶端和伺服器之間傳輸資料的API
從XMLHttpRequest介面來看:
[NoInterfaceObject]
interface XMLHttpRequestEventTarget: EventTarget {
attribute EventHandler onloadstart;
attribute EventHandler onprogress;
attribute EventHandler onabort;
attribute EventHandler onerror;
attribute EventHandler onload;
attribute EventHandler ontimeout;
attribute EventHandler onloaded;
};
interface XMLHttpRequestUpload: XMLHttpRequestEventTarget {
};
enum XMLHttpRequestResponseType {
"",
"arraybuffer",
"blob",
"document",
"json",
"text"
};
[Constructor]
interface XMLHttpRequest: XMLHttpRequestEventTarget {
//event handler
attribute EventHandler onreadystatechange;
//states
const unsigned short UNSENT = 0;
const unsigned short OPENED = 1;
const unsigned short HEADERS_RECEIVED = 2;
const unsigned short LOADING = 3;
const unsigned short DONE = 4;
readonly attribute unsigned short readyState;
//request
void open(ByteString method,[EnsureUTF16] DOMString url);
void open(ByteString method,[EnsureUTF16] DOMString url,boolean async,optional [EnsureUTF16] DOMString? username = null,optional [EnsureUTF16] DOMString? password = null);
void setRequestHeader(ByteString header,ByteString value);
attribute unsigned lond timeout;
attribute boolean withCredentials;
readonly attribute XMLHttpRequestUpload upload;
void send(optional (ArrayBufferView or Blob or [EnsureUTF16] DOMString or FormData)?data=null);
//response
ByteString?getResponseHeader(ByteString header);
ByteString?getAllResponseHeader();
void overrideMimeType(DOMString mime);
readonly attribute unsigned short status;
readonly attribute ByteString statusText;
attribute XMLHttpRequestResponseType responseType;
readonly attribute any response;
readonly attribute DOMString responseText;
readonly attribute Document? responseXML;
}
每一個XMLHttpRequest都有一個唯一的與之關聯的XMLHttpRequestUpload物件
例項:
var formData = new FormData();
formData.append('name','Kuang');
formData.append('password','Kuang')
var xhr = new XMLHttpRequest();
xhr.timeout = 300;
xhr.responseType = 'json';
xhr.open('POST',test.json',true);
xhr.onreadystatechange = function() {
if(this.readyState === this.DONE){
if(this.status === 200 || this.status === 304){
}
}
}
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xhr.send(formData);
XMLHttpRequest詳解
事件
實現XMLHttpRequestEventTarget的事件:
onloadstart
onprogress
onabort
onerror
onload
ontimeout
onloaded
自身定義的事件:
onreadystatechange
狀態
常量:
UNSENT = 0
OPENED = 1;
HEADERS_RECEIVED = 2;
LOADING = 3;
DONE = 4;
readyState
是一個只讀屬性可取以上五個常量的值,當readyState改變是將出發onreadystatechange事件。
request相關
方法:
open()
開啟一個請求
open(method,url,async,[name],[password]);
method: 請求方法POST,GET
url: 請求地址
async: 是否使用非同步方式發起請求
setRequestHeader()
設定請求頭
setRequestHeader(header,value);
header: 請求頭型別
value: 請求頭值
採用追加方式設定
send()
發起請求
send(arraybuffer|blob|formdata|string);
發起一個請求,可附帶資料,傳送query string時需要設定setRequestheader('Content-Type','application/x-www-form-urlencoded')
屬性
timeout
//設定請求超時時間
withCredentials
/*
發起同域請求時,request header中會自動新增上cookie。而傳送跨域請求時cookie並不會新增進request header
造成這個問題的原因是:在CORS標準中做了規定,預設情況下,瀏覽器在傳送跨域請求時,不能傳送任何認證資訊(credentials)如"cookies"和"HTTP authentication schemes"。除非xhr.withCredentials為true(xhr物件有一個屬性叫withCredentials,預設值為false)。
所以根本原因是cookies也是一種認證資訊,在跨域請求中,client端必須手動設定xhr.withCredentials=true,且server端也必須允許request能攜帶認證資訊(即response header中包含Access-Control-Allow-Credentials:true),這樣瀏覽器才會自動將cookie加在request header中。
另外,要特別注意一點,一旦跨域request能夠攜帶認證資訊,server端一定不能將Access-Control-Allow-Origin設定為*,而必須設定為請求頁面的域名。
*/
upload
//XMLHttpRequestUpload
物件使用者上傳,實現了XMLHttpRequestEventTarget介面,故帶有相應的事件處理
response相關
方法:
getResponseHeader
獲取某一請求頭
getResponseHeader(header);
//返回特定請求頭的值
getAllResponseHeader
獲取全部請求頭
getAllResponseHeader()
//返回所有請求頭組成的字串
overrideMimeType
overrideMimeType是xhr level 1就有的方法,所以瀏覽器相容性良好。這個方法的作用就是用來重寫response的content-type,這樣做有什麼意義呢?比如:server 端給客戶端返回了一份document或者是 xml文件,我們希望最終通過xhr.response拿到的就是一個DOM物件,那麼就可以用xhr.overrideMimeType(‘text/xml; charset = utf-8’)來實現。
獲取圖片的例項
var xhr = new XMLHttpRequest();
//向 server 端獲取一張圖片
xhr.open('GET', '/path/to/image.png', true);
// 這行是關鍵!
//將響應資料按照純文字格式來解析,字符集替換為使用者自己定義的字符集
xhr.overrideMimeType('text/plain; charset=x-user-defined');
xhr.onreadystatechange = function(e) {
if (this.readyState == 4 && this.status == 200) {
//通過 responseText 來獲取圖片檔案對應的二進位制字串
var binStr = this.responseText;
//然後自己再想方法將逐個位元組還原為二進位制資料
for (var i = 0, len = binStr.length; i < len; ++i) {
var c = binStr.charCodeAt(i);
//String.fromCharCode(c & 0xff);
var byte = c & 0xff;
}
}
};
xhr.send();
程式碼示例中xhr請求的是一張圖片,通過將 response 的 content-type 改為’text/plain; charset=x-user-defined’,使得 xhr 以純文字格式來解析接收到的blob 資料,終端使用者通過this.responseText拿到的就是圖片檔案對應的二進位制字串,最後再將其轉換為 blob 資料。
屬性:
status
請求成功後的狀態
statusText
請求成功後的狀態文字
responseType
responseType是xhr level 2新增的屬性,用來指定xhr.response的資料型別,目前還存在些相容性問題,可以參考本文的【XMLHttpRequest的相容性】這一小節。那麼responseType可以設定為哪些格式呢,我簡單做了一個表,如下:
值 | 資料型別 | 說明 |
---|---|---|
“” | String字串 | 預設不設定responseType時 |
text | Sting字串 | |
arraybuffer | ArrayBuffer物件 | |
blob | Blob對像 | |
formdata | FormData物件 | FormData例項 |
document | Document物件 | 希望返回XML格式資料時使用 |
下面是同樣是獲取一張圖片的程式碼示例,相比xhr.overrideMimeType,用xhr.response來實現簡單得多。
var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png', true);
//可以將`xhr.responseType`設定為`"blob"`也可以設定為`" arrayBuffer"`
//xhr.responseType = 'arrayBuffer';
xhr.responseType = 'blob';
xhr.onload = function(e) {
if (this.status == 200) {
var blob = this.response;
...
}
};
xhr.send();
response
返回與設定的responseType一致的資料
responseText
當responseType為"text"
或""
時才有此屬性
responseXML
當responseType為"text"
,""
,doument
時才有此屬性