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
請求過程詳解XMLHttpRequest
實例從上面的的代碼能夠看出,建立一個XHR
實例方式爲:緩存
var xhr = new XMLHttpRequest();
實例建立好後,首先須要啓動一個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
請求。app
xhr.open('get', 'http://www.baidu.com', true) xhr.send(null)
send()
方法接受一個參數,爲http
請求發送的數據(一般用於'post'方法),若是爲null
,表示不發送數據。至此,一個異步的http
請求就發送到了服務器。異步
若是將open
方法的第三個參數設爲false
,即爲同步請求,當收到服務器的響應後,相應的數據會自動填充到XHR
對象的屬性中,主要包括如下四個:ide
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狀態碼 }
若是將open
方法的第三個參數設爲true
,即爲異步請求。那麼就須要一個事件來通知程序異步請求的結果是否返回。XHR
對象中的readyState
屬性,表示請求/響應整個過程所處的階段,它有五個值分爲對應五個階段:post
open()
方法。open()
方法,但未調用send()
方法。send()
方法,但未收到響應。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爲不帶參數
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
類型等等,後面慢慢更新。