Ajax 處理服務端響應
在瀏覽器發送 Ajax 請求之后,下一步驟自然是服務器響應。服務器在接收到請求之后會進行一系列處理步驟,最終返回結果。而與此同時,客戶端會在接收到返回的結果之后進行界面的展示或者數據的處理。
本章節主講 Ajax 收到返回數據后處理服務器響應過程。
前言
本章節將會從兩個方面來講解 Ajax 如何處理服務端響應,它們分別是:
- 處理的時機
- 處理的方法
如果你不知道 Ajax 是如何獲取服務端響應內容的,或者你對 HTTP 狀態碼沒有一個初步的了解,甚至你還不知道一個 Ajax 請求過程中各個階段的狀態表示,那么,我相信這個章節會很適合你。接下來讓我們步入正題,一起來看看 Ajax 是如何處理服務端響應的。
1. 何時處理響應
首先思考一個問題,我們應該在什么時機處理服務端的響應呢?
我們知道,Ajax 可以發送異步請求,那數據的返回當然也不可能是同步返回的。客戶端只有等到服務端數據返回才能進行數據的下一步處理。如果服務端沒有正確響應,或者說服務端的響應還沒結束,那么客戶端是無法獲得正確響應的。講得俏皮一點,客戶端在這個時候還得看服務端的臉色。
那么,在代碼中我們要在什么樣的時機開始處理響應呢?
這里,我們有必要了解一下 XMLHttpRequest.readyState
和 XMLHttpRequest.status
。
1.1 XMLHttpRequest.readyState
在客戶端與服務器的通信過程中,XMLHttpRequest.readyState 體現著當前請求以及服務端響應的狀態。當 xhr.readyState == 4
的時候,代表著服務器響應完成。
其他的 readyState 狀態碼還有 0 、1、2、3,他們分別代表著:
0:狀態為 UNSENT。表示創建了但還沒有調用 open 方法。
1:狀態為 OPENED。表示已經調用了 open 方法。
2:狀態為 HEADERS_RECEIVED。表示已經調用了 send 方法,且頭部和狀態也可獲得。
3:狀態為 LOADING。表示正在下載中。
4:狀態為 DONE。表示響應已經完成。
從 readyState 的狀態碼來看,總共有 5 個狀態。并且只有最后一個狀態 4 才能代表著可以開始處理服務端響應數據的時機。
1.2 XMLHttpRequest.status
服務器響應完成之后,我們通常會使用 XMLHttpRequest.status 來查看當前 XMLHttpRequest 響應中的數字狀態碼。這個數字狀態碼是一個無符號短整型狀態碼,代表著我們的 Ajax 請求的狀態成功與否。
在 XMLHttpRequest 中, status 碼對應著標準的 HTTP 狀態碼。并且在請求完成前,該值為 0。
HTTP 狀態碼很多,這里就不做過多的鋪開,具體可以到 HTTP 響應代碼 進行學習和查閱。接下來我們來講幾個常見的狀態碼。
是的,這也是很常見的兩個狀態碼。
1.2.1 200 和 304 狀態碼
在 HTTP 狀態碼中,200 代表著 HTTP 請求成功,而 304 代表著由于瀏覽器緩存原因,GET 請求命中并返回了緩存中的數據。結合 上面 XMLHttpRequest.readyState , 假設請求成功,我們的響應模塊應該如下:
xhr.open("GET", "http://localhost:8080/simple/get?mk=慕課網");
xhr.send();
xhr.onreadystatechange = function() {
// 當前 this 為 xhr
if (this.readyState == 4) {
if (this.status === 200 || this.status === 304) {
// code ...
}
}
};
在后端設置了協商緩存的情況下,我們來看看效果:
第一次請求資源:
刷新頁面,進行第二次請求同樣的資源:
由于瀏覽器的緩存機制,GET請求有可能會緩存我們的請求內容。上面前后兩次請求中,第一次請求的時候獲取新的內容,返回的是 200 的狀態碼;而第二次再進行獲取,我們就有可能獲取第二圖的結果,使用的是本地緩存。因此,在對 Ajax 成功的判斷中,我們不應該遺漏 304 狀態碼的判斷。
1.2.2 404 和 500 狀態碼
有正確的返回,那當然也會有錯誤的返回。打個比方,讓我們來假設這樣的場景:
- 客戶端發送一個請求,剛好請求的接口找不到,因為服務端并沒有提供。
- 客戶端發送一個請求,服務端內部發生錯誤了。
如果遇到這樣的情況,Ajax 當然不能坐以待斃——我們總不該不把任何響應告訴用戶吧!真實的情況是,Ajax 會返回我們相應的 status ,客戶端根據該 status 進行必要的操作。
首先,我們來請求一個捏造的接口,即服務端并沒有支持的接口。
html 關鍵容器:
<div id="container"></div>
JavaScript 腳本關鍵代碼:
var container = document.getElementById('container')
xhr.onreadystatechange = function() {
// 當前 this 為 xhr
if (this.readyState == 4) {
if (this.status === 200 || this.status === 304) {
container.innerHTML = "當前狀態碼為: " + this.status;
} else {
container.innerHTML = "當前錯誤狀態碼為: " + this.status; // 主要看這里,出現非 200 和 304 狀態會在這邊進行顯示
}
}
};
看看運行后的效果圖:
404 Not Found,顯而易見,當我們在查詢的時候,服務端找不到對應的資源的時候就會返回該狀態碼,表示你要找的東西沒有,不存在。在我們的實際工作中,我們經常會遇到這樣的錯誤,往往這個時候你就應該警惕:
- 是不是你的請求 url 寫錯了?
- 是不是前后端線上資源不同步?比方說后端還沒上線對應接口而你已經在開始在代碼中請求了。
講完 404 狀態碼,我們接下來繼續來看看一個很常見的場景,服務器內部發生錯誤了?。。〈a沿用上一個示例,接口改為服務端提供的接口,這次我們會在服務端假設發生錯誤,并返回 500 錯誤。
來看看請求的結果:
事實上,500 錯誤碼也是非常常見的,500 Internal Server Error 代表著服務端錯誤,如果我們在開發過程中遇到這樣的錯誤,那么,就需要后端的同學來查找原因了。
除此之外,HTTP 狀態碼還有很多,每個都有不同的含義,這里也不會做過多的展開,有興趣的同學可以做一個額外的學習查閱。HTTP 協議中,狀態碼可以讓我們在請求之后,獲知請求的狀態。客戶端也能夠以此做出相應的響應。
2. 如何獲取響應內容
要獲取響應內容,當然是 XMLHttpRequest 對象下的幾大法器:responseText 、 responseXML 和 response。其中:
- responseText: 一個 DomString,返回一個純文本的值。 當該值為 “” 的時候,表示這個請求還沒有開始
send()
;當該值為 null 的時候,表示請求失敗。 - responseXML: 處理 XML 響應。返回一個包含請求檢索的 HTML 和 XML 的 Document。 當請求還沒有
send()
,或者失敗了,甚至是解析失敗的時候,該值為 null 。當 responseType 不是 “” 或者 "document"的時候,會報錯。 - response: 返回響應正文。返回類型可以有 DOMString、 Blob 、ArrayBuffer 、Document 或 JavaScript Object ,這取決于 responseType。
了解獲取響應內容的這 3 個屬性,接下來,我們會分別返回 DomString、XML 和 Json 類型數據來展示著響應內容。
核心響應代碼:
xhr.onreadystatechange = function() {
if (this.readyState == 4) {
if (this.status === 200 || this.status === 304) {
var res = this.response
var resText = this.responseText
var resXml = this.responseXML
console.log(res, resText, resXml) // 分別打印三者
}
}
};
2.1 返回 DomString
服務端返回內容:
‘text’
請求結果:
Content-type:
可以看到,當返回的是一個 DomString 的時候,responseText 和 response 都有值,而 responseXML 因為解析失敗為 null。
2.2 返回 XML
服務端返回內容:
<data>Hello World</data>
請求結果:
Content-type:
這一次我們的 XML 正常解析了,并且在控制臺上可以看到打印出了一個 Document,而 response 和 responseText 分別打印了該 XML 的文本形式。
2.3 返回 Json
服務端返回內容:
{a:1}
請求結果:
Content-type:
當返回的是一個 Json 類型數據的時候,response 和 responseText 分別為對應的文本值,而 responseXML 因為解析失敗成了 null。
以上展示了 Ajax 獲取服務端響應的三種類型的數據,簡單的展示給大家 XMLHttpRequest 的 response、responseText 和 responseXML 在不同數據類型下的表現,希望以此能夠加深大家對 XMLHttpRequest 的了解。
3. 小結
- 處理 Ajax 請求,我們應該在適當的時機進行處理。我們應該在
xhr.readyState == 4
,并且xhr.status === 200 || xhr.status === 304
的時候正確獲取響應的內容; - XMLHttpRequest.readyState 體現著當前請求以及服務端響應的狀態;
- XMLHttpRequest.status 即 XMLHttpRequest 響應中的數字狀態碼。這個數字狀態碼是一個無符號短整型狀態碼,代表著我們的 Ajax 請求的狀態成功與否;
- HTTP 狀態碼有很多,包括 404、 500 等,每一個包含著不一樣的含義;
- 獲取服務器響應內容,我們可以使用 responseText 、 responseXML 和 response 。其中,responseText 返回一個純文本的值,responseXML 返回一個包含請求檢索的 HTML 和 XML 的 Document,而 response 返回響應正文。返回類型可以有 DOMString、 Blob 、ArrayBuffer 、Document 或 JavaScript Object ,這取決于 responseType。