本文將會根據(jù)自己的理解,來闡述Ajax, Axios, Fetch他們之間的區(qū)別
1 、JQuery ajax
$.ajax({
type: 'POST',
url: url,
data: data,
dataType: dataType,
success: function () {},
error: function () {}
});
Ajax是對原生XHR的封裝,為了達(dá)到我們跨越的目的,增添了對JSONP的支持。經(jīng)過這么多年的更新維護(hù),不得不承認(rèn)它已經(jīng)很成熟,能夠滿足我們的基本需求,但是隨著react,vue新一代框架的興起,以及ES規(guī)范的完善,更多API的更新,它逐漸暴露了自己的不足
- 針對MVC的編程設(shè)計,不符合現(xiàn)在前端MVVM的趨勢
- 基于原生的XHR開發(fā),XHR本身的架構(gòu)不夠清晰
- JQuery較大,單純使用ajax卻要引入整個JQuery非常的不合理
- 雖然axios不支持jsonp,但是可以通過引入jsonp模塊來解決
2 、Axios
axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
Vue2.0之后,自從尤雨溪推薦大家用axios替換JQuery ajax,Axios快速的得到大家的關(guān)注。Axios本質(zhì)就是對原生XHR的封裝,增加了Promise的實,符合最新的ES規(guī)范,從它的官網(wǎng)上可以看到它有以下幾條特性:
- 從 node.js 創(chuàng)建 http 請求
- 支持 Promise API
- 客戶端支持防止CSRF(請求中攜帶cookie)
- 提供了一些并發(fā)請求的接口(重要,方便了很多的操作)
Axios既提供了并發(fā)的封裝,體積也較小,也沒有下文會提到的fetch的各種問題,當(dāng)之無愧是現(xiàn)在最應(yīng)該選用的請求的方式。
3、 Fetch
fetch號稱是AJAX的替代品,fetch是基于原生的XMLHttpRequest對象來實現(xiàn)數(shù)據(jù)請求的,同時也是基于Promise實現(xiàn)鏈?zhǔn)秸{(diào)用的。它的好處在《傳統(tǒng) Ajax 已死,F(xiàn)etch 永生》中提到有以下幾點:
- 符合關(guān)注分離,沒有將輸入、輸出和用事件來跟蹤的狀態(tài)混雜在一個對象里
- 更好更方便的寫法,諸如:
try {
let response = await fetch(url);
let data = await response.json();
console.log(data);
} catch(e) {
console.log("error:", e);
}
使用 await 后,告別面條式調(diào)用,將異步寫成同步,身心舒暢。從上圖可以看到await 后面可以跟 Promise 對象,表示等待 Promise resolve() 才會繼續(xù)向下執(zhí)行,如果 Promise 被 reject() 或拋出異常則會被外面的 try...catch 捕獲。
坦白說,Jquery還是Axios都已經(jīng)將xhr封裝的足夠好,使用起來也足夠方便,但是Fetch還是得到很多開發(fā)者的認(rèn)可,說明它還是存在很多優(yōu)勢的:
- 更加底層,提供的API豐富(request, response)
- 脫離了XHR,是ES規(guī)范里新的實現(xiàn)方式
- 跨域處理(mode為"no-cors")
fetch('/testPost', {
method: 'post',
mode: 'no-cors',
data: {}
}).then(function() {});
但是在使用fetch的時候,也會遇到了一些問題:
- fetch只對網(wǎng)絡(luò)請求報錯,對400,500都當(dāng)做成功的請求,需要封裝去處理
- fetch默認(rèn)不會帶cookie,需要添加配置項fetch(url, {credentials: 'include'})
- fetch不支持abort,不支持超時控制,使用setTimeout及Promise.reject的實現(xiàn)的超時控制并不能阻止請求過程繼續(xù)在后臺運行,造成了流量的浪費
- fetch沒有辦法原生監(jiān)測請求的進(jìn)度,而XHR可以
- 所有版本的 IE 均不支持原生 Fetch,fetch-ie8 會自動使用 XHR 做 polyfill。但在跨域時有個問題需要處理。IE8, 9 的 XHR 不支持 CORS 跨域,不支持傳 Cookie!所以推薦使用 fetch-jsonp
PS: fetch的具體問題大家可以參考:《fetch沒有你想象的那么美》《fetch使用的常見問題及解決方法》
xhr+promise的實現(xiàn)原理如下:
function Promise(fn) {
this.resolveFn = null;
this.rejectFn = null;
var _this = this;
function resolve(data) {
var f = _this.resolveFn;
f(data);
}
function reject(err) {
var f = this.rejectFn;
f(err);
}
fn(resolve,reject);
}
Promise.prototype.then = function (f) {
this.resolveFn = f; return this;
};
Promise.prototype.catch = function (f) {
this.rejectFn = f; return this;
};
function ajax(url,suc,fail) {
var xhr = new XMLHttpRequest();
xhr.open('GET',url, true);
xhr.onreadystatechange = function () {
if(xhr.readyState == 4){
if(xhr.status == 200){
suc(xhr.responseText)
} else {
console.log(err);
fail(xhr.responseText);
}
}
};
xhr.send(null);
}
function fetch(url) {
console.log('fetch start')
return new Promise(function (resolve,reject) {
ajax(url,function (res) {
resolve(res);
},function (err) {
console.log(err);
reject(err);
})
})
}
fetch('/test').then(function (res) {
console.log(JSON.parse(res));
}).catch (function (err) {
console.log(err);
})