扒一扒 EventServiceProvider 源代碼
Ajax
用一句話來說就是無須刷新頁面即可從服務器取得數據。註意,雖然Ajax
翻譯過來叫異步JavaScript
與XML
,但是獲得的數據不一定是XML
數據,現在服務器端返回的都是JSON
格式的文件。
完整的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
請求過程詳解
1. 創建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
事件,進而調用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
事件用於簡化對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
事件會在瀏覽器接收數據期間周期觸發,代表整個請求過程的進度,它的事件處理程序onprogress
接收一個event
對象,event.target
是XHR
對象,另外event
還有三個屬性:
-
lengthComputable
:Boolean值,進度信息是否可用。 -
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
扒一扒 EventServiceProvider 源代碼