最近,react 項目,使用 fetch 來進行 http 請求。遇到的問題是 fetch 超時 須要作額外處理;爲此,特地查詢了 fetch 相關的資料,整理了下;javascript
瀏覽器發起 http 請求,有兩種方式,XMLHttpRequest(xhr) 和 fetch;其中 xhr 是咱們常常使用的方式,fetch 是在 ES6 引入的,fetch 返回有一個 Promise 對象,寫法更加簡便友好;html
在個人項目中,我使用的是isomorphic-fetch
。如今我對於這個包的理解,能夠 cross-runtime,也就是區分環境 node 仍是 瀏覽器;前端
fetch 用法,MDN 中,講得比較清楚,在這裏和這裏java
// fetch 返回Response的信息 { body: ReadableStream; bodyUsed: false; headers: Headers; ok: true; redirected: false; status: 200; statusText: "OK"; type: "cors"; url: "http://some-website.com/some-url"; __proto__: Response; }
請求的資源都存儲在 body 中,做爲一種可讀的流。因此須要調用一個恰當方法將可讀流轉換爲咱們可使用的數據。node
通常使用 response.json();若是是 xml 格式的,使用 response.text();若是是圖片資源,使用 response.blob();react
- method: GET, POST, PUT, DELETE, HEAD。 - url: url地址。 - headers: 請求頭相關參數。 - referrer : no-referrer, client或者一個網址。默認爲client。 - mode: cors, no-cors, same-origin, navigate。默認爲cors。Chrome(v47~)目前的默認值是 same-origin。 - credentials: omit, same-origin, include。默認值omit。Chrome(v47~)目前的默認值是 include。 - redirect: follow, error, manual。Chrome(v47~)目前的默認值是 manual。 - integrity: Subresource Integrity(子資源完整性, SRI)的值 - cache: default, no-store, reload, no-cache, 或者 force-cache - body: 要加到要求中的內容。注意,method爲GET或者HEAD時不使用這個值。
前端請求的時候都會設計到 token 權限驗證,不少時候是存在 cookie 裏面的.fetch 裏面又一個參數 credentials 設計 cookie
credentials 有三個值:git
fetch 跨域也有對應的參數設置 modees6
fetch 返回問題描述
當一個請求發送完成,服務返回狀態碼,fetch 不會 reject 這個 response,仍然 resolve,可是 response.ok 會設置成 false.不少時候咱們會二次封裝 fetch reject error.github
處理 404 500web
目前 fetch 沒有傳統 ajax 的 abort 方法,還在草案之中
timeout 解決方案
使用 promise 的 race, 由於 promise 裏面的 resolve 和 reject 只能執行一次, 利用 race reject 一個 error.
上面的 abort 並無真正的 abort 這次請求,只是經過 promise promise reject 一個 error 而已.我在翻閱 fetch 的源碼的時候發現了這個
var p = Promise.race([ fetch("/resource-that-may-take-a-while"), new Promise(function (resolve, reject) { setTimeout(() => reject(new Error("request timeout")), 5000); }), ]); p.then((response) => console.log(response)); p.catch((error) => console.log(error));
原生 fetch 方法 可使用 AbortController 來中斷;fetch 源碼,支持使用 signal 來進行中斷;
// fetch 源碼 if (request.signal && request.signal.aborted) { return reject(new DOMException("Aborted", "AbortError")); }
具體代碼以下:
// 1 秒後停止 let controller = new AbortController(); setTimeout(() => controller.abort(), 1000); try { let response = await fetch("/article/fetch-abort/demo/hang", { signal: controller.signal, }); } catch (err) { if (err.name == "AbortError") { // handle abort() alert("Aborted!"); } else { throw err; } }
具體看 這裏
fetch 封裝,對於 json text 圖片格式處理,以及 timeout、相關報錯等做了處理,能夠點擊獲取;
總體文章,可能會有些問題,若有疑問,歡迎留言或者微信交流,共同窗習進步!
fetch-MDN
fetch-源碼
Fetch:停止(Abort)
Isomorphic-Fetch 的詭異部份
fetch 詳解
對 fetch timeout 的思考
fetch 使用的常見問題及解決辦法
AJAX 與 Fetch API