fetch API

轉自:http://blog.csdn.net/renfufei/article/details/51494396javascript

AJAX半遮半掩的底層API是飽受詬病的一件事情. XMLHttpRequest 並非專爲Ajax而設計的. 雖然各類框架對 XHR 的封裝已經足夠好用, 但咱們能夠作得更好。更好用的API是 fetch 。下面簡單介紹 window.fetch 方法, 在最新版的 Firefox 和 Chrome 中已經提供支持。html

XMLHttpRequest

在我看來 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

請求頭(Request Headers)

自定義請求頭信息極大地加強了請求的靈活性。咱們能夠經過 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'
});

可使用的方法包括: appendhasgetset, 以及 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 簡介

Request 對象表示一次 fetch 調用的請求信息。傳入 Request 參數來調用 fetch, 能夠執行不少自定義請求的高級用法:

  • method - 支持 GETPOSTPUTDELETEHEAD
  • url - 請求的 URL
  • headers - 對應的 Headers 對象
  • referrer - 請求的 referrer 信息
  • mode - 能夠設置 corsno-corssame-origin
  • credentials - 設置 cookies 是否隨請求一塊兒發送。能夠設置: omitsame-origin
  • redirect - followerrormanual
  • integrity - subresource 完整性值(integrity value)
  • cache - 設置 cache 模式 (defaultreloadno-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 簡介

Response 表明響應, fetch 的 then 方法接收一個 Response 實例, 固然你也能夠手動建立 Response 對象 —— 好比在 service workers 中可能會用到. Response 能夠配置的參數包括:

  • type - 類型,支持: basiccors
  • url
  • useFinalURL - Boolean 值, 表明 url 是不是最終 URL
  • status - 狀態碼 (例如: 200404, 等等)
  • 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響應

假設須要請求 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 方法仍是很方便的。

處理基本的Text / HTML響應

JSON 並不老是理想的請求/響應數據格式, 那麼咱們看看如何處理 HTML或文本結果:

fetch('/next/page')
  .then(function(response) {
    return response.text();
  }).then(function(text) { 
    // <!DOCTYPE ....
    console.log(text); 
  });

 

如上面的代碼所示, 能夠在 Promise 鏈式的 then 方法中, 先返回 text() 結果 ,再獲取 text 。

處理Blob結果

若是你想經過 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), 而且將其讀完。

提交表單數據(Posting Form Data)

另外一種經常使用的 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!

未完的故事(Unwritten Story)

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日

原文連接: https://davidwalsh.name/fetch

相關文章
相關標籤/搜索