最近在研究React這個框架,成功的成爲了一名新的入坑着。用過React的都知道React的強大主要是在於它的生態的強大,React說的再大不過也就是一個UI框架罷了。不過咱們學習react也主要由於這個生態,有facebook支持,質量相對有保障,衍生出的react-native, react-canvas等輪子在不少場景下能夠直接拿來用。碎片化是React當前的狀態,好比flux庫,promise庫,utils函數庫,dom操做庫,ajax庫等等,每一個點都有2-3個庫在開源社區處於競爭狀態,各有所長,你們根據自身的須要去選擇。而我打算用Fetch做爲ajax庫來擺脫jquery這個千年不變的大殺器。前端
咱們一提到局部刷新,先後端交互,異步加載等首先想到的ajax,好像在咱們的認知中除了ajax就沒有別的了。其實咱們都被這種觀念誤導了,ajax只是對於XMLHttpRequest的一種封裝,咱們談及Ajax技術的時候,一般意思就是基於XMLHttpRequest的Ajax,它是一種可以有效改進頁面通訊的技術。而Fetch API則是XMLHttpRequest的最新替代技術, 它是W3C的正式標準。react
下面咱們看一下Fetch的兼容性jquery
整體來講,最新的瀏覽器都開始慢慢的兼容它了,可是想讓它獨立的用於前端項目仍是任重而道遠啊。。。git
若是你想獨立在前端項目中兼容Fetch,能夠考慮看這篇文章使用fetch遇到過的坑可是我不推薦去本身部署Fetch。github
我是在React項目中瞭解到Fetch的,使用的包是:whatwg-fetchweb
前面說了那麼多,身爲吃瓜羣衆的咱們就是好奇:那他有什麼優勢能讓顛覆了整個前端行業的ajax退位讓賢呢?ajax
XMLHttpRequest 是一個設計粗糙的 API,不符合關注分離(Separation of Concerns)的原則,配置和調用方式很是混亂,並且基於事件的異步模型寫起來也沒有現代的 Promise,generator/yield,async/await 友好。npm
Fetch 的出現就是爲了解決 XHR 的問題,拿例子說明:json
使用 XHR 發送一個 json 請求通常是這樣:canvas
var xhr = new XMLHttpRequest(); xhr.open('GET', url); xhr.responseType = 'json'; xhr.onload = function() { console.log(xhr.response); }; xhr.onerror = function() { console.log("Oops, error"); }; xhr.send();
使用 Fetch 後,頓時看起來好一點(其實jquery的ajax也實現了Promise)
fetch(url).then(function(response) { return response.json(); }).then(function(data) { console.log(data); }).catch(function(e) { console.log("Oops, error"); });
使用 ES6 的 箭頭函數 後:
fetch(url).then(response => response.json()) .then(data => console.log(data)) .catch(e => console.log("Oops, error", e))
如今看起來好不少了,但這種 Promise 的寫法仍是有 Callback 的影子,並且 promise 使用 catch 方法來進行錯誤處理的方式有點奇怪。不用急,下面使用 async/await 來作最終優化:
注:async/await 是很是新的 API,屬於 ES7,目前尚在 Stage 1(提議) 階段,這是它的完整規範。使用 Babel 開啓 runtime 模式後能夠把 async/await 無痛編譯成 ES5 代碼。也能夠直接使用 regenerator 來編譯到 ES5。
try { let response = await fetch(url); let data = await response.json(); console.log(data); } catch(e) { console.log("Oops, error", e); } // 注:這段代碼若是想運行,外面須要包一個 async function
duang~ 的一聲,使用 await 後,寫異步代碼就像寫同步代碼同樣爽。await 後面能夠跟 Promise 對象,表示等待 Promise resolve() 纔會繼續向下執行,若是 Promise 被 reject() 或拋出異常則會被外面的 try...catch 捕獲。
Promise,generator/yield,await/async 都是如今和將來 JS 解決異步的標準作法,能夠完美搭配使用。這也是使用標準 Promise 一大好處。最近也把項目中使用第三方 Promise 庫的代碼所有轉成標準 Promise,爲之後全面
使用 async/await 作準備。
以上資料來自 傳統 Ajax 已死,Fetch 永生
可是我認爲Fetch最不一樣於ajax的是讓咱們對於請求頭的設置更加方便,更加靈活。
對於傳統的XMLHttpRequest而言,你必須使用它的一個實例來執行請求和檢索返回的響應。 可是經過Fetch API,咱們還可以明確的配置請求對象。你能夠經過Request構造器函數建立一個新的請求對象,這也是建議標準的一部分。 第一個參數是請求的URL,第二個參數是一個選項對象,用於配置請求。請求對象一旦建立了, 你即可以將所建立 的對象傳遞給fetch()方法,用於替代默認的URL字符串。示例代碼以下:
var req = new Request(URL, {method: 'GET', cache: 'reload'}); fetch(req).then(function(response) { return response.json(); }).then(function(json) { insertPhotos(json); });
上面的代碼中咱們指明瞭請求使用的方法爲GET,而且指定不緩存響應的結果。
有關Request對象的另外一件更酷的事在於,你還能夠基於原有的對象建立一個新的對象。 新的請求和舊的並無什麼不一樣,但你能夠經過稍微調整配置對象,將其用於不一樣的場景。 例如,你能夠基於原有的GET請求建立一個POST請求,它們具備相同的請求源。代碼以下:
// 基於req對象建立新的postReq對象 var postReq = new Request(req, {method: 'POST'});
每一個Request對象都有一個header屬性,在Fetch API中它對應了一個Headers對象。 經過Headers對象,你可以修改請求頭。不只如此,對於返回的響應,你還能輕鬆的返回響應頭中的各個屬性。 可是須要注意的是,響應頭是隻讀的。
var headers = new Headers(); headers.append('Accept', 'application/json'); var request = new Request(URL, {headers: headers}); fetch(request).then(function(response) { console.log(response.headers); });
在上面的代碼中,你能夠經過Headers構造器來獲取這個對象,用於爲新的Request對象配置請求頭。
類似的,你能夠建立一個Response對象:
function responseDemo() { var headers = new Headers({ 'Content-Type': 'application/json', 'Cache-Control': 'max-age=3600' }); var response = new Response( JSON.stringify({photos: {photo: []}}), {status: 200, headers: headers} ); response.json().then(function(json) { insertPhotos(json); }); }
Request和Response都徹底遵循HTTP標準。
以上資料來自 深刻淺出Fetch API
其實整合這篇文章毛目的沒有,就是由於注意用post提交數據時記得設置'Content-Type'爲'application/x-www-form-urlencoded; charset=UTF-8'