先參考MDN的什麼是AJAX
AJAX是異步的JavaScript和XML(Asynchronous JavaScript And XML)。簡單點說,就是使用 XMLHttpRequest 對象與服務器通信。 它可以使用JSON,XML,HTML和text文本等格式發送和接收數據。AJAX最吸引人的就是它的“異步”特性,也就是說他可以在不重新刷新頁面的情況下與服務器通信,交換數據,或更新頁面。
使用AJAX的兩個特性
- 在不重新加載頁面的情況下發送請求給服務器。
- 接受並使用從服務器發來的數據。
AJAX請求過程是什麼樣的
先看代碼
function request(){
let httpRequest = new XMLHttpRequest();
//要在函數閉包內創建XHR變量,避免被其他request相互覆蓋;
if(!httpRequest){
alert('Giving up :( Cannot create an XMLHTTP instance');
return false;
}
httpRequest.onreadystatechange = alertContents;
httpRequest.open('GET', 'test.html');
httpRequest.send();
}
function alertContents() {
if (httpRequest.readyState === XMLHttpRequest.DONE) {
if (httpRequest.status === 200) {
alert(httpRequest.responseText);
} else {
alert('There was a problem with the request.');
}
}
}
創建XMLHttpRequest對象
let httpRequest = new XMLHttpRequest();
什麼是onreadystatechange
只要 readyState 屬性發生變化,就會調用相應的處理函數。
在這個例子中,處理函數爲alertContents。要注意的是,函數名後沒有參數,因爲你把一個引用賦值給了函數,而不是真正的調用了它。下面會講關於這個處理函數的具體實現。
還有onload()
onreadystatechange顧名思義,每次state變化的時候都會調用被給的函數,如果只想在狀態爲完成的時候被調用,可以使用onload來代替。
open() 初始化
- 不管get還是post,都要先open()。
- 第一個參數是HTTP請求方法 - 有GET,POST,HEAD以及服務器支持的其他方法。 保證這些方法一定要是大寫字母,否則其他一些瀏覽器(比如FireFox)可能無法處理這個請求。
- 第二個參數是你要發送的URL。由於安全原因,默認不能調用第三方URL域名。 確保你在頁面中使用的是正確的域名,否則在調用 open() 方法是會有 “權限被拒絕” 錯誤提示。一個容易犯的錯誤是你企圖通過 domain.tld 訪問網站,而不是使用 www.domain.tld。
- 第三個參數是可選的,用於設置請求是否是異步的。如果設爲 true (默認設置),JavaScript執行會持續,並且在服務器還沒有響應的情況下與頁面進行交互。
send() 發送
上面的就是一個get情景中,用send()的例子
再提供一個post例子
post要設定相應的request header,調用setRequestHeader()
var xhr = new XMLHttpRequest();
xhr.open("POST", '/server', true);
//如果要post就要設定相應的request header
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function() { //這裏定義onreadystatechange前面已經講過了
if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
// 請求完畢,做一些處理
}
}
xhr.send("foo=bar&lorem=ipsum");//正式發送的send()調用
處理onreadystatechange的函數實現
我們知道會把一個函數賦予xhr.onreadystatechange。那麼這個函數應該做什麼?
首先,函數要檢查請求的狀態。如果狀態的值是 XMLHttpRequest.DONE (對應的值是4),意味着服務器響應收到了並且是沒問題的,然後就可以繼續執行。
if (httpRequest.readyState === XMLHttpRequest.DONE) {
...
} else {
...
}
readyState對應值
- 0 UNSENT 還沒open()
- 1 OPENED 已經open()了
- 2 HEADERS_RECEIVED 已經send()了
- 3 LOADING 獲取返回數據中
- 4 DONE 完成
接下來,檢查HTTP響應的 response code。 可能的響應碼都已經列在表中 W3C響應碼列表。在下面的例子中,我們通過檢查響應碼 200 OK 區別對待成功和不成功的AJAX調用。
if (httpRequest.status === 200) {
...
} else {
...
}
粗略的響應碼解釋
- 2XX 成功
- 3XX 重新導向
- 4XX 請求有問題
- 5XX 服務端有問題
一切檢查後,那麼怎麼獲取返回數據?
- httpRequest.responseText – 服務器以文本字符的形式返回
- httpRequest.responseXML – 以 XMLDocument 對象方式返回,之後就可以使用JavaScript來處理
那麼經常看到的jquery中的ajax是什麼樣的?
我們平常用jquery的ajax都是傳一個對象,來具體自己想做什麼樣的請求。
那麼實現ajax的時候,也是先要從這傳進來的一個對象裏面找參數。處理完了以後就用這些得到的參數去做請求就可以了。
粗略的實現
function ajax(options){
if(window.XMLHttpRequest){
let xhr = new XMLHttpRequest;
}else{
let xhr = new ActiveXObject();//IE6 and oler
}
//從option獲取一些參數
let method = options.type || 'GET';
let dataType = options.dataType || 'application/x-www-form-urlencoded';
let params = options.data;
let success = options.success;
let fail = option.fail;
...
//設置onreadystatechange
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.status === 200){
//call success
}else{
//call fail
}
}
//正式進行請求
if(method == 'GET){
xhr.open('GET',url + '?' + params,true);
xhr.send();
}else if(method == 'POST'){
xhr.open('POST',url, true);
xhr.setRequestHeader('Content-Type', dataType);
xhr.send(params);
}else{
...other method handler
}
}
當然還可以fetch
Fetch 是瀏覽器提供的原生 AJAX 接口。這裏不做過多介紹。
要重點提到的就是fetch請求返回的是一個Promise,所以對獲取數據處理要用then()。
一些例子
fetch('/data.json')
.then(res => {
res.text() // response body (=> 還是返回Promise,需要再then())
res.json() // parse via JSON (=> 還是返回Promise,需要再then())
res.status //=> 200
res.statusText //=> 'OK'
res.redirected //=> false
res.ok //=> true
res.url //=> 'http://site.com/data.json'
res.type //=> 'basic'
// ('cors' 'default' 'error'
// 'opaque' 'opaqueredirect')
res.headers.get('Content-Type')
})
參考信息
MDN 什麼是AJAX?
MDN XMLHttpRequest
阮一峯ES6指南 Promise對象
fetch cheatsheet