
Why Fetch
在開發(fā)過程中,我們向服務(wù)端發(fā)送請(qǐng)求,一般會(huì)使用三種方式, XMLHttpRequest(XHR),F(xiàn)etch ,jQuery實(shí)現(xiàn)的AJAX。
其中, XMLHttpRequest(XHR)和Fetch是瀏覽器的原生API,jquery的ajax其實(shí)是封裝了XHR。
讓我們首先來比較一下這三者的使用示例。
XMLHttpRequest
var xhr;
if (window.XMLHttpRequest) { // Mozilla, Safari...
xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
try {
xhr = new ActiveXObject('Msxml2.XMLHTTP');
} catch (e) {
try {
xhr = new ActiveXObject('Microsoft.XMLHTTP');
} catch (e) {}
}
}
if (xhr) {
xhr.onreadystatechange = onReadyStateChange;
xhr.open('POST', '/api', true);
// 設(shè)置 Content-Type 為 application/x-www-form-urlencoded
// 以表單的形式傳遞數(shù)據(jù)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('username=admin&password=root');
}
// onreadystatechange 方法
function onReadyStateChange() {
// 該函數(shù)會(huì)被調(diào)用四次
console.log(xhr.readyState);
if (xhr.readyState === 4) {
// everything is good, the response is received
if (xhr.status === 200) {
console.log(xhr.responseText);
} else {
console.log('There was a problem with the request.');
}
} else {
// still not ready
console.log('still not ready...');
}
}
從上邊的代碼可以看出,XMLHttpRequest 是一個(gè)非常粗糙的API,不符合關(guān)注分離(Separation of Concerns)的原則,配置和調(diào)用方式非?;靵y,前端程序員們不僅要做各個(gè)瀏覽器的兼容性,還飽受回調(diào)地獄的折磨,這顯然不是一個(gè)好的選擇。
jQuery實(shí)現(xiàn)AJAX
$.ajax({
method: 'POST',
url: '/api',
data: { username: 'admin', password: 'root' }
})
.done(function(msg) {
alert( 'Data Saved: ' + msg );
});
jQuery作為一個(gè)使用人數(shù)最多的庫(kù),其AJAX很好的封裝了原生AJAX的代碼,在兼容性和易用性方面都做了很大的提高,而且jQuery還把jsonp裝在了AJAX里面,這樣我們就可以開心的跨域了?。。?!對(duì)比原生AJAX的實(shí)現(xiàn),使用jQuery實(shí)現(xiàn)的AJAX就異常簡(jiǎn)單了.
但是,筆鋒一轉(zhuǎn),我們?nèi)匀惶用摬涣艘粋€(gè)問題,回調(diào)地獄。。。。
Fetch
fetch(...).then(fun2)
.then(fun3) //各依賴有序執(zhí)行
.....
.catch(fun)
從上邊的代碼可以看出,fetch用起來想jQuery一樣簡(jiǎn)單,雖然還是有Callback的影子,但是看起來舒服多了
詳解Fetch API
兼容性
注意:由于Fetch API是基于Promise設(shè)計(jì),舊瀏覽器不支持Promise,需要使用pollyfill es6-promise
- Fetch使用說明
fetch(url, options).then(function(response) {
// handle HTTP response
}, function(error) {
// handle network error
})
說明:
a. fetch api返回的是一個(gè)promise對(duì)象
b.Options:
- method(String): HTTP請(qǐng)求方法,默認(rèn)為
GET - body(String): HTTP的請(qǐng)求參數(shù)
- headers(Object): HTTP的請(qǐng)求頭,默認(rèn)為{}
- credentials(String): 默認(rèn)為
omit,忽略的意思,也就是不帶cookie;還有兩個(gè)參數(shù),same-origin,意思就是同源請(qǐng)求帶cookie;include,表示無論跨域還是同源請(qǐng)求都會(huì)帶cookie
c.第一個(gè)then函數(shù)里面處理的是response的格式,這里的response具體如下:

- status(number): HTTP返回的狀態(tài)碼,范圍在100-599之間
- statusText(String): 服務(wù)器返回的狀態(tài)文字描述,例如
Unauthorized,上圖中返回的是Ok - ok(Boolean): 如果狀態(tài)碼是以2開頭的,則為true
- headers: HTTP請(qǐng)求返回頭
- body: 返回體,這里有處理返回體的一些方法
- text(): 將返回體處理成字符串類型
- json(): 返回結(jié)果和 JSON.parse(responseText)一樣
- blob(): 返回一個(gè)Blob,Blob對(duì)象是一個(gè)不可更改的類文件的二進(jìn)制數(shù)據(jù)
- arrayBuffer()
- formData()
- Fetch常見坑
- 兼容性

如caniuse所示,IE瀏覽器完全不支持fetch,移動(dòng)端的很多瀏覽器也不支持,所以,如果要在這些瀏覽器上使用Fetch,就必須使用fetch polyfill
- cookie傳遞
必須在header參數(shù)里面加上credentials: 'include',才會(huì)如xhr一樣將當(dāng)前cookies帶到請(qǐng)求中去 - fetch和xhr的不同
fetch雖然底層,但是還是缺少一些常用xhr有的方法,比如能夠取消請(qǐng)求(abort)方法
fetch在服務(wù)器返回4xx、5xx時(shí)是不會(huì)拋出錯(cuò)誤的,這里需要手動(dòng)通過,通過response中的ok字段和status字段來判斷
- 實(shí)踐總結(jié)
我們?cè)趯?shí)際應(yīng)用中雖然會(huì)因?yàn)樗鼪]有interceptor等原因還需要再封裝一層,但fetch api仍然不失為一個(gè)非常贊的API。。。。
4.參考