轉自:http://blog.csdn.net/renfufei/article/details/51494396javascript
AJAX半遮半掩的底層API是飽受詬病的一件事情. XMLHttpRequest 並非專爲Ajax而設計的. 雖然各類框架對 XHR 的封裝已經足夠好用, 但咱們能夠作得更好。更好用的API是 fetch
。下面簡單介紹 window.fetch
方法, 在最新版的 Firefox 和 Chrome 中已經提供支持。html
在我看來 XHR 有點複雜, 我不想解釋爲何「XML」是大寫,而「Http」是「駱峯式」寫法。使用XHR的方式大體以下:java
// 獲取 XHR 很是混亂! if (window.XMLHttpRequest) { // Mozilla, Safari, ... request = new XMLHttpRequest(); } else if (window.ActiveXObject) { // IE try { request = new ActiveXObject('Msxml2.XMLHTTP'); } catch (e) { try { request = new ActiveXObject('Microsoft.XMLHTTP'); } catch (e) {} } } // 打開鏈接, 發送數據. request.open('GET', 'https://davidwalsh.name/ajax-endpoint', true); request.send(null);
咱們能夠看出, XHR 實際上是很雜亂的; 固然, 經過 JavaScript 框架能夠很方便地使用XHR。git
fetch
的基本使用fetch
是全局量 window
的一個方法, 第一個參數是URL:程序員
// url (必須), options (可選) fetch('/some/url', { method: 'get' }).then(function(response) { }).catch(function(err) { // 出錯了;等價於 then 的第二個參數,但這樣更好用更直觀 :( });
和 Battery API 相似, fetch API 也使用了 JavaScript Promises 來處理結果/回調:github
// 對響應的簡單處理 fetch('/some/url').then(function(response) { }).catch(function(err) { // 出錯了;等價於 then 的第二個參數,但這樣更直觀 :( }); // 鏈式處理,將異步變爲相似單線程的寫法: 高級用法. fetch('/some/url').then(function(response) { return //... 執行成功, 第1步... }).then(function(returnedValue) { // ... 執行成功, 第2步... }).catch(function(err) { // 中途任何地方出錯...在此處理 :( });
若是你還不習慣 then
方式的寫法,那最好學習一下,由於很快就會全面流行。web
自定義請求頭信息極大地加強了請求的靈活性。咱們能夠經過 new Headers()
來建立請求頭:ajax
// 建立一個空的 Headers 對象,注意是Headers,不是Header var headers = new Headers(); // 添加(append)請求頭信息 headers.append('Content-Type', 'text/plain'); headers.append('X-My-Custom-Header', 'CustomValue'); // 判斷(has), 獲取(get), 以及修改(set)請求頭的值 headers.has('Content-Type'); // true headers.get('Content-Type'); // "text/plain" headers.set('Content-Type', 'application/json'); // 刪除某條請求頭信息(a header) headers.delete('X-My-Custom-Header'); // 建立對象時設置初始化信息 var headers = new Headers({ 'Content-Type': 'text/plain', 'X-My-Custom-Header': 'CustomValue' });
可使用的方法包括: append, has, get, set, 以及 delete 。須要建立一個 Request
對象來包裝請求頭:json
var request = new Request('/some-url', { headers: new Headers({ 'Content-Type': 'text/plain' }) }); fetch(request).then(function() { /* handle response */ });
下面介紹 Response
和Request
的使用方法!api
Request 對象表示一次 fetch 調用的請求信息。傳入 Request 參數來調用 fetch, 能夠執行不少自定義請求的高級用法:
method
- 支持 GET
, POST
, PUT
, DELETE
, HEAD
url
- 請求的 URLheaders
- 對應的 Headers
對象referrer
- 請求的 referrer 信息mode
- 能夠設置 cors
, no-cors
, same-origin
credentials
- 設置 cookies 是否隨請求一塊兒發送。能夠設置: omit
, same-origin
redirect
- follow
, error
, manual
integrity
- subresource 完整性值(integrity value)cache
- 設置 cache 模式 (default
, reload
, no-cache
)Request
的示例以下:
var request = new Request('/users.json', { method: 'POST', mode: 'cors', redirect: 'follow', headers: new Headers({ 'Content-Type': 'text/plain' }) }); // 使用! fetch(request).then(function() { /* handle response */ });
只有第一個參數 URL 是必需的。在 Request
對象建立完成以後, 全部的屬性都變爲只讀屬性. 請注意, Request
有一個很重要的 clone
方法, 特別是在 Service Worker API 中使用時 —— 一個 Request 就表明一串流(stream), 若是想要傳遞給另外一個 fetch
方法,則須要進行克隆。
fetch
的方法簽名(signature,可理解爲配置參數), 和 Request
很像, 示例以下:
fetch('/users.json', { method: 'POST', mode: 'cors', redirect: 'follow', headers: new Headers({ 'Content-Type': 'text/plain' }) }).then(function() { /* handle response */ });
由於 Request 和 fetch 的簽名一致, 因此在 Service Workers 中, 你可能會更喜歡使用 Request 對象。關於 ServiceWorker 的相關博客請等待後續更新!
Response 表明響應, fetch 的 then
方法接收一個 Response
實例, 固然你也能夠手動建立 Response
對象 —— 好比在 service workers 中可能會用到. Response 能夠配置的參數包括:
type
- 類型,支持: basic
, cors
url
useFinalURL
- Boolean 值, 表明 url
是不是最終 URLstatus
- 狀態碼 (例如: 200
, 404
, 等等)ok
- Boolean值,表明成功響應(status 值在 200-299 之間)statusText
- 狀態值(例如: OK
)headers
- 與響應相關聯的 Headers 對象. // 在 service worker 測試中手動建立 response // new Response(BODY, OPTIONS) var response = new Response('.....', { ok: false, status: 404, url: '/' }); // fetch 的 `then` 會傳入一個 Response 對象 fetch('/') .then(function(responseObj) { console.log('status: ', responseObj.status); });
Response
提供的方法以下:
clone()
- 建立一個新的 Response 克隆對象.error()
- 返回一個新的,與網絡錯誤相關的 Response 對象.redirect()
- 重定向,使用新的 URL 建立新的 response 對象..arrayBuffer()
- Returns a promise that resolves with an ArrayBuffer.blob()
- 返回一個 promise, resolves 是一個 Blob.formData()
- 返回一個 promise, resolves 是一個 FormData 對象.json()
- 返回一個 promise, resolves 是一個 JSON 對象.text()
- 返回一個 promise, resolves 是一個 USVString (text).假設須要請求 JSON —— 回調結果對象 response 中有一個json()
方法,用來將原始數據轉換成 JavaScript 對象:
fetch('https://davidwalsh.name/demo/arsenal.json').then(function(response) { // 轉換爲 JSON return response.json(); }).then(function(j) { // 如今, `j` 是一個 JavaScript object console.log(j); });
固然這很簡單 , 只是封裝了 JSON.parse(jsonString)
而已, 但 json
方法仍是很方便的。
JSON 並不老是理想的請求/響應數據格式, 那麼咱們看看如何處理 HTML或文本結果:
fetch('/next/page') .then(function(response) { return response.text(); }).then(function(text) { // <!DOCTYPE .... console.log(text); });
如上面的代碼所示, 能夠在 Promise 鏈式的 then
方法中, 先返回 text()
結果 ,再獲取 text 。
若是你想經過 fetch 加載圖像或者其餘二進制數據, 則會略有不一樣:
fetch('flowers.jpg') .then(function(response) { return response.blob(); }) .then(function(imageBlob) { document.querySelector('img').src = URL.createObjectURL(imageBlob); });
響應 Body mixin 的 blob()
方法處理響應流(Response stream), 而且將其讀完。
另外一種經常使用的 AJAX 調用是提交表單數據 —— 示例代碼以下:
fetch('/submit', { method: 'post', body: new FormData(document.getElementById('comment-form')) });
提交 JSON 的示例以下:
fetch('/submit-json', { method: 'post', body: JSON.stringify({ email: document.getElementById('email').value answer: document.getElementById('answer').value }) });
很是很是簡單, 媽媽不再用擔憂個人Ajax!
fetch
是個很實用的API , 當前還不容許取消請求, 這使得不少程序員暫時不會考慮它。
新的 fetch
API 比起 XHR 更簡單也更智能。畢竟,它就是專爲AJAX而設計的, 具備後發優點. 而我已經火燒眉毛地使用了, 即便如今兼容性還不是那麼好!
本文簡單介紹了 fetch
。更多信息請訪問 Fetch簡介。若是你要使用 fetch, 也想尋找 polyfill(兼容代碼), 請點擊: GitHub上的fetch實現 https://github.com/github/fetch。
翻譯人員: 鐵錨 http://blog.csdn.net/renfufei
翻譯時間: 2016年5月22日
原文時間: 2016年4月15日