當我們聲明了一個XMLHttpRequest對象的實例的時候,使用for-in來循環遍歷一下這個實例(本文使用的是chrome45版本瀏覽器),我們會發現在這個實例上綁定了一些內容,我把這些內容進行了一下分類:
一、配置項
也就是對xhr對象進行配置。① timeout : 配置請求超時時間。
② withCredentials:是否攜帶發送提供憑據,在下面會進行詳細的說明。
二、屬性項
也就是指一些請求發送或完成過程中可能會被用戶讀取或使用到的一些值。① readyState:xhr的狀態碼。
② status:http狀態碼。
③ statusText:http狀態說明文本。
④ response:響應。
⑤ responseType:響應類型。
⑥ responseURL:響應的URL路徑。
⑦ responseText:響應的文本數據。
⑧ responseXML:響應的XML數據。
⑨ upload:上傳對象,在下面會詳細說明。
三、方法項
就是可以通過這些方法進行一些交互,如發送請求,獲取或設置頭部信息等等。① open:打開一個xhr請求。
② setRequestHeader:設置請求頭信息。
③ send:發送請求。
④ abort:中斷請求。
⑤ getResponseHeader:獲取某一響應頭內容。
⑥ getAllResponseHeaders:獲取所有響應頭內容。
⑦ overrideMimeType:覆蓋服務器返回的MIME類型。
xhr對象還有一些例如addEventListener、removeEventListener等等的方法,由於和xhr沒太大聯系,所以這里就不再寫出來了。
四、回調項
回調項的作用是用來當xhr對象發送一些變化的時候來觸發某些操作使用的。① onabort:發生中斷事件。
② onerror:產生了錯誤。
③ ontimeout:請求超時了。
④ onreadystatechange:xhr狀態碼發生了改變。
⑤ onloadstart:當process開始的時候。(關於procress我們在后面再說)
⑥ onprogress:每次progress正在進行的時候。
⑦ onload:每次progress成功的時候。
⑧ onloadend:當process結束的時候。
五、不可變值
在xhr中存在UNSENT,OPENED,HEADERS_RECEIVED,LOADING,DONE這五個不可變值,他們所代表的內容分別是0,1,2,3,4這五個數字,在open方法調用之前,xhr對象的status屬性是UNSENT,也就是0,當調用了open方法之后,但是還沒有調用send的時候status的值是OPENED,當調用了send方法,已經接收到響應的頭信息時,status就會變為HEADERS_RECEIVED,正在接受響應內容的時候status就是LOADING,請求已完成並且接受完所有響應內容的時候就會變為DONE。下面對這五個分類的前四個已經里面的內容進行一個詳細的記錄~(有人可能會問,不是上面分了五個分類嗎,可素第五個分類就那5個不可改變的值,也沒有什么好說的+_+)
一、配置項
① timeout
timeout是用來設置超時時間的,默認的值是0,也就是說沒有超時限制,不管請求多久都不會觸發超時。可以給他設置一個類型為數字的值,代表多少毫秒之后如果沒有收到響應就觸發超時事件(ontimeout)。
② withCredentials
這個值是來配置是否在發送的時候攜帶着憑據,默認值是false,也就是默認不攜帶。所謂的憑據指的就是cookie、HTTP認證及客戶端SSL證明等信息。這個是在CORS跨域的時候與服務器的Access-Control-Allow-Credentials進行配合使用的,如果發送了攜帶憑據的請求,但是服務器的響應里面沒有Access-Control-Allow-Credentials是true這個值的頭,那么瀏覽器就會由於同源限制把響應給屏蔽掉,並且調用xhr的oerror事件。
例如有下面這一段代碼:
javascript(示例代碼,沒有考慮兼容性)
那么肯定會報錯,首先因為當客戶端的withCredentials設置為true的時候,服務端的Access-Control-Allow-Origin就不能設置為*來代表任意一個域了,需要把請求的域給寫出來,如: http://192.168.1.106;另外服務器端需要把Access-Control-Allow-Credentials設置為true,否則會報錯:
所以正確的服務端代碼應該是:
var xhr=new XMLHttpRequest(); xhr.withCredentials=true; xhr.onreadystatechange=function(){ if(xhr.readyState==4){ if(xhr.status==200){ console.log("success!"); } } } xhr.onerror=function(e){ console.log("error!"); } xhr.open("GET","http://127.0.0.1/withCredentials.php"); xhr.send(null);
如果在服務端的代碼試下嘛這樣子的:
php
header("Access-Control-Allow-Origin: *"); echo "ok";
XMLHttpRequest cannot load http://127.0.0.1/withCredentials.php. Credentials flag is "true", but the "Access-Control-Allow-Credentials" header is "". It must be "true" to allow credentials. Origin "http://192.168.1.106" is therefore not allowed access.
php
header("Access-Control-Allow-Origin: http://192.168.1.106"); header("Access-Control-Allow-Credentials: true"); echo "ok";
二、屬性項
① readyState
這個是xhr對象的狀態碼,就像是一本史書一樣,貫穿於整個xhr的使用歷史,從最開始沒有進行任何操作的時候為UNSENT,到OPENED,HEADERS_RECEIVED,LOADING,DONE的一步步變化,我們可以使用onreadystatechange這一回調函數來偵聽它的變化,我們使用的最多的就是當它的值為4,也就是等於DONE的時候來對響應結果進行進一步的處理。
② status
由於xhr對象發送的是一個http請求,那么肯定就會有http的狀態碼,status就是代表了狀態碼,當一個請求成功的時候那么狀態碼就是2XX或者是304,2XX代表的是服務器成功響應了,304代表是從瀏覽器緩存中讀取了內容。
javascript
if(xhr.readyState==4){ if(xhr.status>=200&&xhr.status<300 ||="" xhr.status="=304){" console.log(xhr.response);="" }="" }<="" code=""></300>
③ statusText
這個屬性的作用其實不大,就是對上面的http狀態碼status進行一個描述,比如說200狀態碼的描述就是OK。
④ response
字面意思是響應,就是響應的主體,這個值依賴於responseType,不同的responseType就會使得response的類型不同。
下面是不同的responseType和response類型對照
① "" :空值代表response是一個 DOMString 類型的值。
② arraybuffer:response是一個 ArrayBuffer 類型的值。
③ blob:response是一個 Blob 類型的值。
④ document:response是一個 Document 類型的值。
⑤ json:response是一個JSON類型的值。
⑥ text:response是一個DOMString類型的值,與responseType是空值相同。
另外還有一些瀏覽器獨有的值,如moz-chunked-text,moz-blob等等,這些都是某種瀏覽器沒有標准化的內容,所以這里也就不贅述了,如果有興趣可以閱讀MDN的此篇文章-》 傳送門。
⑤ responseType
① "" :空值代表response是一個 DOMString 類型的值。
② arraybuffer:response是一個 ArrayBuffer 類型的值。
③ blob:response是一個 Blob 類型的值。
④ document:response是一個 Document 類型的值。
⑤ json:response是一個JSON類型的值。
⑥ text:response是一個DOMString類型的值,與responseType是空值相同。
另外還有一些瀏覽器獨有的值,如moz-chunked-text,moz-blob等等,這些都是某種瀏覽器沒有標准化的內容,所以這里也就不贅述了,如果有興趣可以閱讀MDN的此篇文章-》 傳送門。
這就是響應的類型,在上面已經說過它與response的關系了,默認值就是為空。
⑥ responseURL
返回響應序列化的URL地址,如果URL是null就返回空字符串。如在上面最開始說withCredentials的時候的代碼中的responseURL的值就是
“http://127.0.0.1/withCredentials.php”。
⑦ responseText
如果請求成功就是一個帶有響應數據文本的DOMString,如果請求不成功那么這個值就是null。
⑧ responseXML
是一個包含響應數據的文檔(document),如果請求失敗或者是請求返回的內容不能解析為一個xml或者是html,那么這個值就是null。
⑨ upload
這是一個新的api,返回一個XMLHttpRequestUpload對象,表示上傳過程。這個對象包含與xhr類似的回調函數,可以使用這些回調函數來監聽數據發送過程中的進度(onprogress)、錯誤(onerror)、中斷(onabort)等等。
可以使用這個對象來創建一個上傳內容的進度監測:
javascript
var xhr = new XMLHttpRequest(); var onProgressHandler = function(event) { if(event.lengthComputable) { console.log((event.loaded / event.total) * 100); } else { console.log("Can"t determine the size of the file."); } } xhr.upload.addEventListener("progress", onProgressHandler, false); xhr.open("POST","http://iwenku.net"); xhr.send(data);
三、方法項
① open
用於初始化一個請求,所有ajax請求的第一步都是要構建這么一個請求。在open方法之前xhr的readyState是UNSENT,當調用open方法之后就會變為OPENED。
open方法有5個參數,前兩個是必須的,后面三個是可選的參數。
第一個是用的HTTP方法:可以傳入“GET”、“POST”、“HEAD”等方法。
第二個參數是請求的地址。
第三個參數代表是不是異步(async),默認值為true,也就是使用異步的方式不阻塞主線程,如果值為false,則不使用異步的方式,在主線程知道xhr的請求結束之后才會繼續執行后面的語句。下面有一段xhr的open方法異步和同步的示例:
javascript
var xhr=new XMLHttpRequest(); xhr.open("GET","http://127.0.0.1/openTest.php"); xhr.send(null); xhr.onreadystatechange=function(){ if(xhr.readyState===xhr.DONE){ console.log("done"); } } console.log("response"+xhr.responseText); for(var i=0;i<3;i++){ console.log(i);="" }<="" code=""></3;i++){>
上面open方法沒有傳入第三個參數,也就是使用了默認值true,代表這是一個異步的請求,最后程序的輸出為:
response:
0
1
2
done
如果在上面的代碼中把open的第三個參數設置為false,那么就是使用同步的方式,程序的輸出結果是:
0
1
2
done
response:ok
0
1
2
可以看出來不僅僅是在主線程中順序執行了,而且readystatechange事件也沒有偵聽到。
0
1
2
② setRequestHeader
給指定的HTTP請求頭賦值,這個方法如果要使用的話需要在open方法執行之后並且還沒有執行send方法。
語法:setRequestHeader(請求頭名稱,要賦予的值)
這個方法其實很簡單,之前在一個前端中級交流群里有個朋友提出來怎么來設置多個請求頭,我和他說多次調用這個方法不就行了,其實自己偷偷的去查了一下能不能調用一次這個方法同時改變多個值,事實證明是不行的~。
③ send
發送請求. 如果在open中沒有設置async參數,或者是這個參數設置為了true,那么在調用send方法后send方法會立即返回,不會阻塞主線程,然后繼續執行后面的代碼。如果在open的時候采用的是同步的方式,也就是把第三個參數設置為了false,那么send方法就會阻塞主線程,只有當請求結束的時候才會返回。
send方法可以不傳入數據,也可以傳入ArrayBuffer、Blob、Document、DOMString或者是FormData等類型的數據,當數據類型為document的時候,它在發送之前會進行序列化,在FireFox3之前編碼總是會采用utf8,在這之后會根據body或者xmlEncoding的編碼。
什么是序列化?
序列化是將對象狀態轉換為可保持或傳輸的格式的過程。在javascript中最常用的進行序列化的方法是JSON.stringify,反序列化可以使用JSON.parse來實現。
④ abort
序列化是將對象狀態轉換為可保持或傳輸的格式的過程。在javascript中最常用的進行序列化的方法是JSON.stringify,反序列化可以使用JSON.parse來實現。
如果請求已經被發送,則立刻中止請求。但是這個也只是讓前端結束ajax請求,至於后台會不會也結束請求不再去執行某些操作,那么就得對后端進行設置了。
⑤ getResponseHeader
返回指定的響應頭的值,如果響應頭還沒被接受,或該響應頭不存在,則返回null。
語法:getResponseHeader(相應頭名稱)
javascript
var xhr=new XMLHttpRequest(); xhr.open("GET","http://127.0.0.1/getResponseHeader.php"); xhr.send(null); xhr.onreadystatechange=function(){ if(xhr.readyState===xhr.DONE){ console.log(xhr.getResponseHeader("Content-Type")); } }
上面這一段代碼會輸出”text/html“,也就是說在相應頭中的Content-Type就是這個。
⑥ getAllResponseHeaders
這個方法和上面的getResponseHeader相類似,這個方法返回的是所有的頭部信息,經過實際測試返回的內容數據類型為string。
⑦ overrideMimeType
在瀏覽器中顯示的內容有 HTML、有 XML等等很多類型,瀏覽器就是使用MIME Type,也就是該資源的媒體類型來區分它們,來決定怎么顯示。
媒體類型通常是通過 HTTP 協議,由 Web 服務器告知瀏覽器的,更准確地說,是通過Content-Type 來表示的,例如:Content-Type: text/HTML表示內容是 text/HTML 類型,也就是超文本文件。
這個方法的作用就是重寫由服務器返回的MIME type。這個可用於強制把一個響應流當作“text/xml”來處理和解析,即使服務器沒有指明數據是這個類型。
這個方法需要在open之后,send方法之前進行調用。
四、回調項
① onabort
當一個xhr實例調用abort方法的時候會觸發這個回調,用於處理中斷了一個xhr請求之后的一些事情。這個回調函數會傳入一個XMLHttpRequestProgressEvent類型的參數:

當xhr出現錯誤的時候就會觸發這個回調,也會傳入一個XMLHttpRequestProgressEvent對象。
③ ontimeout
當請求的執行時間超過了timeout設置的時長的時候就會觸發這個超時回調。
④ onreadystatechange
每當 XMLHttpRequest 的屬性 readyState 發生改變時就會觸發這個事件,但是根據實際測試如果open的時候這個ajax請求不是異步的,那么就不會觸發這個事件。
當一個 XMLHttpRequest 請求被 abort() 方法取消時 readystatechange 事件也不會被觸發。
還剩下4個回調,這四個都是關於progress的,所以在這里一起來寫一下~
在 XHR2 (XMLHttpRequest Level 2) 的規范性已經定義了 Progress Event 事件,好讓我們在發送異步請求的時候能夠得知進度。
onloadstart:當process開始的時候觸發。
onloadend:當process結束的時候。
onprogress:每次progress正在進行的時候觸發,會傳入一個XMLHttpRequestProgressEvent對象,可以從這個對象的total屬性、loaded對象等來獲取總大小和已經加載的大小。
onload:每次progress成功的時候觸發。