Ajax
用一句話來說就是無須重新整理頁面即可從伺服器取得資料。注意,雖然
Ajax
翻譯過來叫異步
JavaScript
與
XML
,但是獲得的資料不一定是
XML
資料,現在伺服器端傳回的都是
JSON
格式的檔案。
完整的 Ajax
請求過程
Ajax
Ajax
- 建立
執行個體
XMLHttpRequest
- 發出
請求
HTTP
- 接收伺服器傳回的資料
- 更新網頁資料
下面先看一個紅寶書上給出的發起
Ajax
請求的例子,
API
的用法在後面章節給出。
var xhr = new XMLHttpRequest(); // 建立XMLHttpRequest執行個體
xhr.onreadystatechange = function(){
if (xhr.readyState == 4){ // 判斷請求響應過程階段,4 階段代表已接收到資料
if (xhr.status >=200 && xhr.status < 300 || xhr.status == 304) { // 校驗HTTP狀态碼
console.log(xhr.responseText); // 輸出響應的文本
} else {
console.error(xhr.status, xhr.statusText); // 列印其他HTTP狀态碼
}
}
};
xhr.open('get', 'example.txt', true); // 初始化xhr執行個體,或者說啟動請求
xhr.send(null); // 設定HTTP請求攜帶參數,null為不帶參數
Ajax
請求過程詳解
Ajax
1. 建立 XMLHttpRequest
XMLHttpRequest
從上面的的代碼可以看出,建立一個
XHR
執行個體方式為:
var xhr = new XMLHttpRequest();
2. 發出HTTP請求
執行個體建立好後,首先需要啟動一個
HTTP
請求,使用
XHR
的
open()
方法,
open
方法接受三個參數
XMLHttpRequest.open(method, url, isAsync)
// 例如
xhr.open('get', 'http://www.baidu.com', true)
第一個參數為
http
請求使用方法,如('get','post'等),第二是參數是請求的
url
, 第三個參數代表是否異步發送請求(可選)。調用
open()
方法後會啟動一個
http
請求,但它不會立即發送請求,處于待命狀态。需要注意的是:請求的
url
必須要跟請求源域(origin)同域,也就是說協定、域名、端口号要一緻,跨域請求要使用别的方法。接着調用
send()
方法就會發出這個
http
請求。
xhr.open('get', 'http://www.baidu.com', true)
xhr.send(null)
send()
方法接受一個參數,為
http
請求發送的資料(通常用于'post'方法),如果為
null
,表示不發送資料。至此,一個異步的
http
請求就發送到了伺服器。
3. 接收伺服器傳回的資料
3.1 發送同步請求
如果将
open
方法的第三個參數設為
false
,即為同步請求,當收到伺服器的響應後,相應的資料會自動填充到
XHR
對象的屬性中,主要包括以下四個:
-
:作為響應主體被傳回的文本。responseText
-
: 響應傳回的responseXML
文檔,能接收到的前提是,響應的XML
字段的值為Content-Type
或者text/xml
。application/xml
-
:status
狀态碼。HTTP
-
statusText
狀态碼說明。HTTP
當用戶端收到以上資訊後,首先要判斷
HTTP
狀态碼來确認響應是否成功,狀态碼在200-300之間表示請求成功,同時304代表請求資源未被修改,可使用浏覽器本地緩存。如果成功就可以擷取響應封包主體中的資料了。
xhr.open('get', 'http://www.baidu.com', false)
xhr.send(null)
if (xhr.status >=200 && xhr.status < 300 || xhr.status == 304) { // 校驗HTTP狀态碼
console.log(xhr.responseText); // 輸出響應的文本
} else {
console.error(xhr.status, xhr.statusText); // 列印其他HTTP狀态碼
}
3.2 發送異步請求
open
true
,即為異步請求。那麼就需要一個事件來通知程式異步請求的結果是否傳回。
XHR
對象中的
readyState
屬性,表示請求/響應整個過程所處的階段,它有五個值分為對應五個階段:
- 0:未初始化。未調用
方法。open()
- 1:啟動。已經調用
方法,但未調用open()
send()
- 2:發送。已調用
方法,但未收到響應。send()
- 3: 接收。已經接收到部分響應資料。
- 4:完成。已經接受到全部響應資料。
readyState
的值每變化一次,都會觸發一次
readStatechange
事件,我們定義一個事件處理函數
onreadStatechange()
,并監聽
readyState == 4
狀态,就可以得知響應資料已全部收到,并進行下一步操作。那麼就是文章開頭給出的代碼:
var xhr = new XMLHttpRequest(); // 建立XMLHttpRequest執行個體
xhr.onreadystatechange = function(){
if (xhr.readyState == 4){ // 判斷請求響應過程階段,4 階段代表已接收到資料
if (xhr.status >=200 && xhr.status < 300 || xhr.status == 304) { // 校驗HTTP狀态碼
console.log(xhr.responseText); // 輸出響應的文本
} else {
console.error(xhr.status, xhr.statusText); // 列印其他HTTP狀态碼
}
}
};
xhr.open('get', 'example.txt', true); // 初始化xhr執行個體,或者說啟動請求
xhr.send(null); // 設定HTTP請求攜帶參數,null為不帶參數
補充XHR中三個有用的事件
timeout
事件
timeout
當超出了設定時間還未收到響應,就會觸發
timeout
事件,進而調用
ontimeout
事件處理程式。同時
timeout
也是
XHR
的一個屬性,用于設定這個時間門檻值。下面是用法:
xhr.ontimeout = function() {
alert('timeout!')
}
xhr.open('get', 'http://www.baidu.com', true)
xhr.timeout = 1000 // 時間門檻值設為1秒
xhr.send(null)
load
load
load
事件用于簡化對
readState
值的判斷,響應資料全部接收完畢後(也就是
readState == 4
)會觸發
load
事件,使用
onload
事件處理函數進行後續操作,
onload
會接收一個
event
對象,它的
target
屬性等于
XHR
對象,當然我們在定義這個事件處理函數時也可以不傳入這個參數,來看下面的用法:
var xhr = new XMLHttpRequest()
xhr.onload = function () {
if(xhr.status >=200 && xhr.status < 300 || xhr.status == 304) {
console.log(xhr.responseText); // 輸出響應的文本
} else {
console.error(xhr.status, xhr.statusText); // 列印其他HTTP狀态碼
}
}
xhr.open('get', 'http://www.baidu.com', true)
xhr.send(null)
這樣就不用去關心
readyState
值的變化情況了。當然如果想在特定
readyState
值上做一些邏輯處理,還是要用之前的方法。
progress
progress
這個是很有用的一個事件,
progress
事件會在浏覽器接收資料期間周期觸發,代表整個請求過程的進度,它的事件處理程式
onprogress
接收一個
event
對象,
event.target
是
XHR
對象,另外
event
還有三個屬性:
-
:Boolean值,進度資訊是否可用。lengthComputable
-
:已經接收到的位元組數。position
-
:總共要接收的位元組數,被定義在響應封包的totalSize
字段中。Content-Length
如果響應封包中有
Content-Length
字段,那麼我們就可以計算目前時刻響應資料的加載進度了,這也是之前看到的一個面試題。看下面的代碼:
xhr.onprogress = function(event) {
if(event.lengthComputable) {
console.log(`Received: ${(event.position/event.totalSize).toFixed(4)*100}%`);
}
}
其他還有很多有用的API,如
FormData
表單序列化,
overrideMimeType()
重寫
XHR
響應的
MIME
類型等等,後面慢慢更新。
原文位址:https://segmentfault.com/a/1190000015668383