目錄
- 1. AJAX
- 1.1 簡介
- 1.2 特點
- 1.3 常見狀态碼
- 1.4 使用方法
- 1.5 使用Promise封裝AJAX
- 2. Fetch
- 2.1 Fetch簡介
- 2.2 常用參數
- 2.3 基本用法
- 2.4 響應結果
- 2.5 特點
- 3. axios
- 3.1 axios簡介
- 3.2 基本用法
- 3.3 響應結果
- 3.4 全局配置
- 3.5 攔截器
- 4. async / await
前言:
在前後端互動的過程中,有很多資料請求的方式,例如AJAX、Fetch、axios等等,下面就一一來簡單列舉一下。
我們先來看一下URL的兩種的形式:
- 傳統的URL格式如下:
scheme://host:port/path?query#fragment
其中:
scheme: 表示協定,如Http, Https, Ftp等;
host: 表示所通路資源所在的主機名:如:www.baidu.com;
port: 表示端口号,預設為80;
path: 表示所通路的資源在目标主機上的儲存路徑;
query: 表示查詢條件;
fragment:表示錨點(哈希),用于定位頁面的某個位置。
例如: http://www.baidu.com/search?words=Baidu
- restful形式的URL
(1)HTTP的請求方式:
- GET 查詢
- POST 添加
- PUT 修改
- DELETE 删除
(2)符合規則的URL:(送出方式不同)
http://www.hello.com/books GET
http://www.hello.com/books POST
http://www.hello.com/books/123 PUT(對id為123的資料進行修改)
http://www.hello.com/books/123 DELETE(對id為123的資料進行删除)
1. AJAX
1.1 簡介
AJAX 是 Asynchronous JavaScript and XML 的縮寫,指的是通過 JavaScript 的異步通信,從伺服器擷取 XML 文檔從中提取資料,再更新目前網頁的對應部分,而不用重新整理整個網頁。
1.2 特點
- 優點
- 不需要插件支援(一般浏覽器且預設開啟 JavaScript 即可)
- 使用者體驗極佳(不重新整理頁面即可擷取可更新的資料)
- 提升 Web 程式的性能(在傳遞資料方面做到按需發送,不必整體送出)
- 減輕伺服器和帶寬的負擔(将伺服器的一些操作轉移到用戶端)
- 缺點
- 前進、後退的功能被破壞(因為 AJAX 永遠在目前頁,不會記錄前後頁面)
- 搜尋引擎的支援度不夠(因為搜尋引擎爬蟲還不能了解 JS 引起變化資料的内容)
1.3 常見狀态碼
100 ~ 199 表示連接配接繼續
200 ~ 299 表示各種意義上的成功
300 ~ 399 表示重定向
400 ~ 499 表示各種用戶端錯誤
500 ~ 599
1.4 使用方法
AJAX 包括以下幾個步驟:
- 建立XMLHttpRequest對象,也就是建立一個異步調用對象
- 建立一個新的HTTP請求,并指定其請求的方法、URL及驗證資訊
- 設定響應 HTTP 請求狀态變化的函數
- 發送 HTTP 請求
- 擷取異步調用傳回的資料
- 使用 JavaScript 和 DOM 實作局部重新整理
//原生AJAx
var request = new XMLHttpRequest(); // 建立XMLHttpRequest對象;
request.onreadystatechange = function () { // 狀态發生變化時,函數被回調;
if (request.readyState === 4) { // 成功完成
// 判斷響應結果:
if (request.status === 200) {
// 成功,通過responseText拿到響應的文本:
} else {
// 失敗,根據響應碼判斷失敗原因:
}
} else {
// HTTP請求還在繼續...
}
}
// 發送請求:
request.open("POST","/skill-ajax/a/login",true);
request.setRequestHeader("Content-type","application/x-www-form-urlencoded");
request.send();
alert('請求已發送,請等待響應...');
// readyState值說明
// 0,初始化,XHR對象已經建立,還未執行open
// 1,載入,已經調用open方法,但是還沒發送請求
// 2,載入完成,請求已經發送完成
// 3,互動,可以接收到部分資料
// status值說明
// 200:成功
// 404:沒有發現檔案、查詢或URl
// 500:伺服器産生内部錯誤
使用jQuery進行AJAX請求:
//jQuery中的AJAX
$.ajax({
method: 'GET', // 1.9.0本版前用'type'
url: url,
data: data,
dataType: dataType,
success: function() {
console.log('執行成功');
},
error: function() {
console.log('執行出錯');
}
})
使用jQuery進行AJAX請求時它具有以下特點:
(1)優點:
- 對原生XHR的封裝,做了相容處理,簡化了使用
- 增加了對JSONP的支援,可以簡單處理部分跨域
(2)缺點:
- 如果有多個請求,并且有依賴關系的話,容易形成回調地獄
- 本身是針對MVC的程式設計,不符合現在前端MVVM的浪潮
- ajax是jQuery中的一個方法。如果隻是要使用ajax卻要引入整個jQuery,很不合理
1.5 使用Promise封裝AJAX
這裡不多做介紹,之前寫了一篇相關文章:利用Promise封裝Ajax中get和post方法
2. Fetch
2.1 Fetch簡介
Fetch是基于Promise實作的,支援 async/await,它有更加簡單的資料擷取方式,功能更加強大、更靈活,可以看做是xhr的更新版。
// 原生XHR
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText) // 從伺服器擷取資料
}
}
xhr.send()
// fetch
fetch(url)
.then(response => {
return response.json();
})
.then(data => console.log(data)) // 這裡得到的才是真正的資料
.catch(error => console.log(error))
2.2 常用參數
常用的參數配置:
(1)
method
(String): HTTP請求方法,預設為GET (GET、POST、PUT、DELETE)
(2)
body
(String): HTTP的請求參數
(3)
headers
(Object): HTTP的請求頭,預設為{}
2.3 基本用法
- GET 請求方式
//使用普通URL進行傳遞參數
fetch('/abc?id=123')
.then(response => {
return response.json();
})
.then(data => console.log(data))
.catch(error => console.log(error))
// 使用restful形式進行傳參
fetch('/abc/123',{
method:'get'
}).then(response => {
return response.json();
}).then(data => console.log(data))
.catch(error => console.log(error))
- DELETE請求方式
delete請求方式和get方式類似:
//使用普通URL進行傳遞參數
fetch('/abc?id=123',{
method:'delete'
}).then(response => {
return response.json();
}).then(data => console.log(data))
.catch(error => console.log(error))
// 使用restful形式進行傳參
fetch('/abc/123',{
method:'delete'
}).then(response => {
return response.json();
}).then(data => console.log(data))
.catch(error => console.log(error))
- POST請求方式
//以普通參數形式請求
fetch('/abc',{
method:'post',
body:'uname=zhangsan&psw=123',
headers:{
'Content-Type' : 'application/X-www-form-urlencoded'
}
}).then(response => {
return response.json();
}).then(data => console.log(data))
.catch(error => console.log(error))
// 以json格式進行請求
fetch('/abc',{
method:'post',
body:JSON.stringify({
uname:'zhangsan',
psw:'123'
})
headers:{
'Content-Type' : 'application/json'
}
}).then(response => {
return response.json();
}).then(data => console.log(data))
.catch(error => console.log(error))
- PUT請求方式
put請求方式和post類似:
//以普通參數形式請求
fetch('/abc/123',{ //123要修改資料的id
method:'put',
body:'uname=zhangsan&psw=123',
headers:{
'Content-Type' : 'application/X-www-form-urlencoded'
}
}).then(response => {
return response.json();
}).then(data => console.log(data))
.catch(error => console.log(error))
// 以json格式進行請求
fetch('/abc/123',{
method:'put',
body:JSON.stringify({
uname:'zhangsan',
psw:'123'
})
headers:{
'Content-Type' : 'application/json'
}
}).then(response => {
return response.json();
}).then(data => console.log(data))
.catch(error => console.log(error))
2.4 響應結果
Fetch響應資料的格式主要有以下兩種:
-
:将傳回體處理成字元串類型text()
-
:傳回結果和json()
(responseText)一樣JSON.parse
我們上面使用的是
json()
格式,如果想用
text()
格式,直接替換即可。
2.5 特點
(1)優點:
在配置中,添加
mode:'no-cors'
就可以跨域了
fetch('/users.json', {
method: 'post',
mode: 'no-cors',
data: {}
}).then(function() { /* handle response */ });
(2)缺點:
- fetch隻對網絡請求報錯,對400,500都當做成功的請求,需要封裝去處理
- fetch預設不會帶cookie,需要添加配置項。
- fetch不支援abort,不支援逾時控制,使用setTimeout及Promise.reject的實作逾時控制并不能阻止請求過程繼續在背景運作,造成了流量的浪費。
- fetch沒有辦法原生監測請求的進度,而XHR可以。
3. axios
3.1 axios簡介
axios是一個基于
promise
的HTTP庫,可以用在浏覽器和
node.js
中。它本質也是對原生
XMLHttpRequest
的封裝,隻不過它是
Promise
的實作版本,符合最新的ES規範。
Vue作者尤雨溪推薦使用axios進行資料請求。
axios具有以下特點:
- 支援浏覽器和 node.js
- 支援 promise
- 能攔截請求和響應
- 自動轉換JSON資料
- 提供了并發請求的接口
3.2 基本用法
- GET請求和DELETE請求
get請求和delete請求的用法類似,下面隻寫get請求:
//通過傳統的URL位址傳遞參數
axios.get('/user?id=12345')
.then(function (response) {
console.log(response); // 這是傳回的一個封裝好的對象
console.log(response.data); // 這才是背景響應的真正的資料
})
.catch(function (error) {
console.log(error);
});
//通過restful形式的URL進行傳參
axios.get('/user/id=12345')
.then(function (response) {
console.log(response);
console.log(response.data);
})
.catch(function (error) {
console.log(error);
});
//通過params對象傳遞參數
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
- POST請求和PUT請求
post和put類似,這裡隻列舉post請求方式:
// 通過預設選項傳參(預設傳遞的是json形式的資料)
axios.post('/user', {
uname:'zhangsan',
psw:'123'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
//通過URLSearchParams傳遞參數(application/x-www-form-urlencoded)
const params = new URLSeardhParams();
params . append('uname', 'zhangsan');
params . append ('psw', '123');
axios.post('/user', params)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
- 并發請求
function getUserAccount(){
return axios.get('/user/12345');
}
function getUserPermissions(){
return axios.get('/user/12345/permissions');
}
axios.all([getUserAccount(),getUserPermissions()])
.then(axios.spread(function(acct,perms){
//當這兩個請求都完成的時候會觸發這個函數,兩個參數分别代表傳回的結果
}))
3.3 響應結果
我們上文中隻說了響應的資料
response.data
,響應結果中還有以下主要屬性:
-
: 實際響應回來的資料data
-
: 響應頭資訊headers
-
: 響應狀态碼status
-
: 響應狀态資訊statusText
3.4 全局配置
在發送請求之前,我們可以對axios請求設定全局配置:
// 逾時時間
axios.defaults.timeout = 3000;
//設定預設位址,配置請求的基準URL位址,在請求時就可以不寫這一部分
axios.defaults.baseURL =http://www.baidu.com';
// 設定請求頭
axios.defaults.headers[ 'mytoken'] = 'helloworld'
3.5 攔截器
- 請求攔截器
請求攔截器的作用是在送出請求之前設定一些資訊:
axios.interceptors.request.use(function(config){
//在請求發出之前進行資訊設定
config.headers.mytoken = 'helloworld' // 和全局配置設定請求頭效果一樣,但是更加靈活
return config;
},function(error){
// 處理響應的錯誤資訊
console.log(error);
});
- 響應攔截器
響應攔截器的作用是在擷取資料之前對資料進行一些加工處理:
axios.interceptors.response.use(function(response){
//對傳回的資料進行處理
var data = response.data;
return data;
},function(error){
//處理響應的錯誤資訊
console.log(error);
});
4. async / await
async / await
方法是ES7中引入的新文法,可以更加便捷的進行異步操作。其中:
-
關鍵字用于函數上(async
函數的傳回值是Promise執行個體對象)async
-
關鍵字用于async函數當中(await
可以得到異步的結果)await
async function queryData (id) {
const ret = await axios.get('/data'); //可以直接得到調用結果,不需要再使用then
return ret;
}
// 因為上一步傳回的Promise對象,是以通過調用then,可以直接獲得上面擷取到的資料
queryData.then (ret=> {
console.log (ret)
})
使用
async / await
處理多個異步請求:
async function queryData(id) {
const info = await axios. get('/async1') ;
const ret = await axios . get ( 'async2?info='+info.data) ;
return ret;
}
queryData.then (ret=>{
console.log (ret)
})