Fetch.png
Why Fetch
在開發過程中,我們向服務端發送請求,一般會使用三種方式, XMLHttpRequest(XHR),Fetch ,jQuery實現的AJAX。
其中, XMLHttpRequest(XHR)和Fetch是瀏覽器的原生API,jquery的ajax其實是封裝了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);
// 設置 Content-Type 為 application/x-www-form-urlencoded
// 以表單的形式傳遞數據
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('username=admin&password=root');
}
// onreadystatechange 方法
function onReadyStateChange() {
// 該函數會被調用四次
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 是一個非常粗糙的API,不符合關注分離(Separation of Concerns)的原則,配置和調用方式非常混亂,前端程序員們不僅要做各個瀏覽器的兼容性,還飽受回調地獄的折磨,這顯然不是一個好的選擇。
jQuery實現AJAX
$.ajax({
method: 'POST',
url: '/api',
data: { username: 'admin', password: 'root' }
})
.done(function(msg) {
alert( 'Data Saved: ' + msg );
});
jQuery作為一個使用人數最多的庫,其AJAX很好的封裝了原生AJAX的代碼,在兼容性和易用性方面都做了很大的提高,而且jQuery還把jsonp裝在了AJAX里面,這樣我們就可以開心的跨域了!!!!對比原生AJAX的實現,使用jQuery實現的AJAX就異常簡單了.
但是,筆鋒一轉,我們仍然逃脫不了一個問題,回調地獄。。。。
Fetch
fetch(...).then(fun2)
.then(fun3) //各依賴有序執行
.....
.catch(fun)
從上邊的代碼可以看出,fetch用起來想jQuery一樣簡單,雖然還是有Callback的影子,但是看起來舒服多了
詳解Fetch API
兼容性
注意:由于Fetch API是基于Promise設計,舊瀏覽器不支持Promise,需要使用pollyfill es6-promise
- Fetch使用說明
fetch(url, options).then(function(response) {
// handle HTTP response
}, function(error) {
// handle network error
})
說明:
a. fetch api返回的是一個promise對象
b.Options:
- method(String): HTTP請求方法,默認為
GET
- body(String): HTTP的請求參數
- headers(Object): HTTP的請求頭,默認為{}
- credentials(String): 默認為
omit
,忽略的意思,也就是不帶cookie;還有兩個參數,same-origin
,意思就是同源請求帶cookie;include
,表示無論跨域還是同源請求都會帶cookie
c.第一個then函數里面處理的是response的格式,這里的response具體如下:
image.png
- status(number): HTTP返回的狀態碼,范圍在100-599之間
- statusText(String): 服務器返回的狀態文字描述,例如
Unauthorized
,上圖中返回的是Ok
- ok(Boolean): 如果狀態碼是以2開頭的,則為true
- headers: HTTP請求返回頭
- body: 返回體,這里有處理返回體的一些方法
- text(): 將返回體處理成字符串類型
- json(): 返回結果和 JSON.parse(responseText)一樣
- blob(): 返回一個Blob,Blob對象是一個不可更改的類文件的二進制數據
- arrayBuffer()
- formData()
- Fetch常見坑
- 兼容性
image.png
如caniuse所示,IE瀏覽器完全不支持fetch,移動端的很多瀏覽器也不支持,所以,如果要在這些瀏覽器上使用Fetch,就必須使用fetch polyfill
- cookie傳遞
必須在header參數里面加上credentials: 'include'
,才會如xhr一樣將當前cookies帶到請求中去 - fetch和xhr的不同
fetch雖然底層,但是還是缺少一些常用xhr有的方法,比如能夠取消請求(abort)方法
fetch在服務器返回4xx、5xx時是不會拋出錯誤的,這里需要手動通過,通過response中的ok字段和status字段來判斷
- 實踐總結
我們在實際應用中雖然會因為它沒有interceptor等原因還需要再封裝一層,但fetch api仍然不失為一個非常贊的API。。。。
4.參考