在 JS 中使用 fetch 更加高效地進(jìn)行網(wǎng)絡(luò)請(qǐng)求
在前端快速發(fā)展地過程中,為了契合更好的設(shè)計(jì)模式,產(chǎn)生了 fetch 框架,此文將簡(jiǎn)要介紹下 fetch 的基本使用。
在 AJAX 時(shí)代,進(jìn)行請(qǐng)求 API 等網(wǎng)絡(luò)請(qǐng)求都是通過 XMLHttpRequest 或者封裝后的框架進(jìn)行網(wǎng)絡(luò)請(qǐng)求?,F(xiàn)在產(chǎn)生的 fetch 框架簡(jiǎn)直就是為了提供更加強(qiáng)大、高效的網(wǎng)絡(luò)請(qǐng)求而生,雖然在目前會(huì)有一點(diǎn)瀏覽器兼容的問題,但是當(dāng)我們進(jìn)行 Hybrid App 開發(fā)的時(shí)候,如我之前介紹的 Ionic 和 React Native,都可以使用 fetch 進(jìn)行完美的網(wǎng)絡(luò)請(qǐng)求。
1. fetch 初體驗(yàn)
在 Chrome 瀏覽器中已經(jīng)全局支持了 fetch 函數(shù),打開調(diào)試工具,在 Console 中可以進(jìn)行初體驗(yàn)。先不考慮跨域請(qǐng)求的使用方法,我們先請(qǐng)求同域的資源,如在我的博客頁面中,打開 Console 進(jìn)行如下請(qǐng)求。
fetch("http://blog.parryqiu.com")
.then(function(response)
{
console.log(response)
})```
返回的數(shù)據(jù):

這樣就很快速地完成了一次網(wǎng)絡(luò)請(qǐng)求,我們發(fā)現(xiàn)返回的數(shù)據(jù)也比之前的 XMLHttpRequest 豐富、易用的多。
[](http://blog.parryqiu.com/2016/03/02/using_fetch_in_nodejs/#2-__u5173_u4E8E_fetch__u6807_u51C6_u6982_u89C8)2. 關(guān)于 fetch 標(biāo)準(zhǔn)概覽
雖然 fetch 還不是作為一個(gè)穩(wěn)定的標(biāo)準(zhǔn)發(fā)布,但是在其一直迭代更新的 [標(biāo)準(zhǔn)描述](https://fetch.spec.whatwg.org/) 中,我們發(fā)現(xiàn)已經(jīng)包含了很多的好東西。fetch 支持了大部分常用的 HTTP 的請(qǐng)求以及和 HTTP 標(biāo)準(zhǔn)的兼容,如 HTTP Method,HTTP Headers,Request,Response。
[](http://blog.parryqiu.com/2016/03/02/using_fetch_in_nodejs/#3-_fetch__u7684_u4F7F_u7528)3. fetch 的使用
[](http://blog.parryqiu.com/2016/03/02/using_fetch_in_nodejs/#3-1__u517C_u5BB9_u6D4F_u89C8_u5668_u7684_u5904_u7406)3.1 兼容瀏覽器的處理
可以通過下面的語句處理瀏覽器兼容的問題。
if(self.fetch) {
// 使用 fetch 框架處理
} else {
// 使用 XMLHttpRequest 或者其他封裝框架處理
}```
3.2 一般構(gòu)造請(qǐng)求的方法
使用 fetch 的構(gòu)造函數(shù)請(qǐng)求數(shù)據(jù)后,返回一個(gè) Promise 對(duì)象,處理即可。
fetch("http://blog.parryqiu.com")
.then(function(response)
{ // do something...})```
3.3 fetch 構(gòu)成函數(shù)的其他選項(xiàng)
我們可以將于 HTTP Headers 兼容的格式加入到請(qǐng)求的頭中,如每次 API 的請(qǐng)求我們想不受緩存的影響,那么可以像下面這樣請(qǐng)求:
fetch("http://blog.parryqiu.com", {
headers: {
'Cache-Control': 'no-cache'
}
})
.then(function(response){
// do something...
})```
具體的可選參數(shù)可以查看 這里。如我們還可以這樣使用:
var myHeaders = new Headers();
myHeaders.append("Content-Type", "text/plain");
myHeaders.append("Content-Length", content.length.toString());
myHeaders.append("X-Custom-Header", "ProcessThisImmediately");
var myInit = {
method: 'GET',
headers: myHeaders,
mode: 'cors',
cache: 'default'
};
fetch("http://blog.parryqiu.com", myInit)
.then(function(response){
// do something...
})
3.4 返回的數(shù)據(jù)結(jié)構(gòu)
在請(qǐng)求后的 Response 中,具體的定義在 這里。常用的有:
Response.status 也就是 StatusCode,如成功就是 200
;
Response.statusText 是 StatusCode 的描述文本,如成功就是 OK
;
Response.ok 一個(gè) Boolean 類型的值,判斷是否正常返回,也就是 StatusCode 為 200-299
。
做如下請(qǐng)求:
fetch("http://blog.parryqiu.com")
.then(function(response){
console.log(response.status);
console.log(response.statusText);
console.log(response.ok);
})```
返回的數(shù)據(jù):

[](http://blog.parryqiu.com/2016/03/02/using_fetch_in_nodejs/#3-5_Body__u53C2_u6570)3.5 Body 參數(shù)
因?yàn)樵?Request 和 Response 中都包含 Body 的實(shí)現(xiàn),所以包含以下類型:
ArrayBuffer
ArrayBufferView (Uint8Array and friends)
Blob/File
string
URLSearchParams
FormData
在 fetch 中實(shí)現(xiàn)了對(duì)應(yīng)的方法,并返回的都是 Promise 類型。
[arrayBuffer()](https://developer.mozilla.org/en-US/docs/Web/API/Body/arrayBuffer)
[blob()](https://developer.mozilla.org/en-US/docs/Web/API/Body/blob)
[json()](https://developer.mozilla.org/en-US/docs/Web/API/Body/json)
[text()](https://developer.mozilla.org/en-US/docs/Web/API/Body/text)
[formData()](https://developer.mozilla.org/en-US/docs/Web/API/Body/formData)
這樣處理返回的數(shù)據(jù)類型就會(huì)變的特別地方便,如處理 json 格式的數(shù)據(jù):
var myRequest = new Request('http://api.com/products.json');
fetch(myRequest).then(function(response) {
return response.json().then(function(json) {
for(i = 0; i < json.products.length; i++) {
var name = json.products[i].Name;
var price = json.products[i].Price;
// do something more...
}
});
});```
- 瀏覽器兼容
目前項(xiàng)目給出的瀏覽器支持如下圖,可以通過上面介紹的瀏覽器兼容處理辦法解決此問題,不過相信很快就不需要考慮兼容問題了,在 Hybrid App 開發(fā)中使用基本沒有問題,因?yàn)榛径际腔?Node.js 進(jìn)行開發(fā)的。有朋友提出兼容性問題的嚴(yán)謹(jǐn)性,其實(shí)通過 JS polyfill,已經(jīng)可以獲得很好的支持。
如使用 A window.fetch JavaScript polyfill 可以獲得如下支持。

如使用 fetch-ie8 可以獲得如下支持。

5. 結(jié)語
這里是一個(gè)格式更好的文檔,比標(biāo)準(zhǔn)描述的頁面更加清晰,供參考。https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API在使用 React Native 開發(fā) App 的時(shí)候接觸到了 fetch,發(fā)現(xiàn)的確非常方便高效,框架的設(shè)計(jì)模式也非常清晰靈活,更多的細(xì)節(jié)可以查閱相關(guān)文檔,有什么問題可以留言討論交流。