本文將會(huì)根據(jù)自己的理解障涯,來(lái)闡述Ajax, Axios, Fetch他們之間的區(qū)別
1 纵朋、JQuery ajax
$.ajax({
type: 'POST',
url: url,
data: data,
dataType: dataType,
success: function () {},
error: function () {}
});
Ajax是對(duì)原生XHR的封裝,為了達(dá)到我們跨越的目的祈秕,增添了對(duì)JSONP的支持渺贤。經(jīng)過(guò)這么多年的更新維護(hù),不得不承認(rèn)它已經(jīng)很成熟请毛,能夠滿足我們的基本需求志鞍,但是隨著react,vue新一代框架的興起,以及ES規(guī)范的完善方仿,更多API的更新固棚,它逐漸暴露了自己的不足
- 針對(duì)MVC的編程設(shè)計(jì),不符合現(xiàn)在前端MVVM的趨勢(shì)
- 基于原生的XHR開(kāi)發(fā),XHR本身的架構(gòu)不夠清晰
- JQuery較大仙蚜,單純使用ajax卻要引入整個(gè)JQuery非常的不合理
- 雖然axios不支持jsonp此洲,但是可以通過(guò)引入jsonp模塊來(lái)解決
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ì)就是對(duì)原生XHR的封裝贾节,增加了Promise的實(shí)汁汗,符合最新的ES規(guī)范衷畦,從它的官網(wǎng)上可以看到它有以下幾條特性:
- 從 node.js 創(chuàng)建 http 請(qǐng)求
- 支持 Promise API
- 客戶端支持防止CSRF(請(qǐng)求中攜帶cookie)
- 提供了一些并發(fā)請(qǐng)求的接口(重要,方便了很多的操作)
Axios既提供了并發(fā)的封裝知牌,體積也較小祈争,也沒(méi)有下文會(huì)提到的fetch的各種問(wèn)題,當(dāng)之無(wú)愧是現(xiàn)在最應(yīng)該選用的請(qǐng)求的方式送爸。
3铛嘱、 Fetch
fetch號(hào)稱是AJAX的替代品,fetch是基于原生的XMLHttpRequest對(duì)象來(lái)實(shí)現(xiàn)數(shù)據(jù)請(qǐng)求的袭厂,同時(shí)也是基于Promise實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用的墨吓。它的好處在《傳統(tǒng) Ajax 已死,F(xiàn)etch 永生》中提到有以下幾點(diǎn):
- 符合關(guān)注分離纹磺,沒(méi)有將輸入帖烘、輸出和用事件來(lái)跟蹤的狀態(tài)混雜在一個(gè)對(duì)象里
- 更好更方便的寫(xiě)法,諸如:
try {
let response = await fetch(url);
let data = await response.json();
console.log(data);
} catch(e) {
console.log("error:", e);
}
使用 await 后橄杨,告別面條式調(diào)用秘症,將異步寫(xiě)成同步,身心舒暢式矫。從上圖可以看到await 后面可以跟 Promise 對(duì)象乡摹,表示等待 Promise resolve() 才會(huì)繼續(xù)向下執(zhí)行,如果 Promise 被 reject() 或拋出異常則會(huì)被外面的 try...catch 捕獲采转。
坦白說(shuō)聪廉,Jquery還是Axios都已經(jīng)將xhr封裝的足夠好,使用起來(lái)也足夠方便故慈,但是Fetch還是得到很多開(kāi)發(fā)者的認(rèn)可板熊,說(shuō)明它還是存在很多優(yōu)勢(shì)的:
- 更加底層,提供的API豐富(request, response)
- 脫離了XHR察绷,是ES規(guī)范里新的實(shí)現(xiàn)方式
- 跨域處理(mode為"no-cors")
fetch('/testPost', {
method: 'post',
mode: 'no-cors',
data: {}
}).then(function() {});
但是在使用fetch的時(shí)候干签,也會(huì)遇到了一些問(wèn)題:
- fetch只對(duì)網(wǎng)絡(luò)請(qǐng)求報(bào)錯(cuò),對(duì)400拆撼,500都當(dāng)做成功的請(qǐng)求容劳,需要封裝去處理
- fetch默認(rèn)不會(huì)帶cookie,需要添加配置項(xiàng)fetch(url, {credentials: 'include'})
- fetch不支持abort闸度,不支持超時(shí)控制鸭蛙,使用setTimeout及Promise.reject的實(shí)現(xiàn)的超時(shí)控制并不能阻止請(qǐng)求過(guò)程繼續(xù)在后臺(tái)運(yùn)行,造成了流量的浪費(fèi)
- fetch沒(méi)有辦法原生監(jiān)測(cè)請(qǐng)求的進(jìn)度筋岛,而XHR可以
- 所有版本的 IE 均不支持原生 Fetch,fetch-ie8 會(huì)自動(dòng)使用 XHR 做 polyfill晒哄。但在跨域時(shí)有個(gè)問(wèn)題需要處理睁宰。IE8, 9 的 XHR 不支持 CORS 跨域肪获,不支持傳 Cookie!所以推薦使用 fetch-jsonp
PS: fetch的具體問(wèn)題大家可以參考:《fetch沒(méi)有你想象的那么美》《fetch使用的常見(jiàn)問(wèn)題及解決方法》
xhr+promise的實(shí)現(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);
})