Fetch() 簡介

Matt Gaunt

fetch() 可讓您發出類似 XMLHttpRequest (XHR) 的網路要求。 主要差異在於 Fetch API 使用 Promise 更簡便的 API,避免發生要求中的複雜回呼 XMLHttpRequest API。

瀏覽器支援

  • Chrome:42.
  • Edge:14。
  • Firefox:39。
  • Safari:10.1.

資料來源

如果您沒用過 Promise 請先參閱 JavaScript Promise 簡介

基本擷取要求

以下示範如何透過 XMLHttpRequest 實作 然後使用 fetch。我們想要求存取網址、取得回應以及剖析 匯出為 JSON

XMLHttpRequest

XMLHttpRequest 需要兩個事件監聽器來處理成功 以及呼叫 open()send() 的情況。 MDN 文件範例

function reqListener() {
    var data = JSON.parse(this.responseText);
    console.log(data);
}

function reqError(err) {
    console.log('Fetch Error :-S', err);
}

var oReq = new XMLHttpRequest();
oReq.onload = reqListener;
oReq.onerror = reqError;
oReq.open('get', './api/some.json', true);
oReq.send();

擷取

我們的擷取要求如下所示:

fetch('./api/some.json')
  .then(
  function(response) {
    if (response.status !== 200) {
      console.log('Looks like there was a problem. Status Code: ' +
        response.status);
      return;
    }

    // Examine the text in the response
    response.json().then(function(data) {
      console.log(data);
    });
  }
  )
  .catch(function(err) {
    console.log('Fetch Error :-S', err);
  });

fetch() 要求只需要一個呼叫就能執行與 XHR 相同的工作 範例。為處理回應,我們會先檢查回應狀態 200,則將回應剖析為 JSON。fetch() 要求的回應是 Stream 物件,也就是說, 我們呼叫了 json() 方法,會傳回 Promise。 串流以非同步方式進行。

回應中繼資料

上例顯示了 Response 物件,以及如何 將回應剖析為 JSON。如何處理您可能會想要的其他中繼資料 可存取的標頭,例如標頭:

fetch('users.json').then(function(response) {
    console.log(response.headers.get('Content-Type'));
    console.log(response.headers.get('Date'));

    console.log(response.status);
    console.log(response.statusText);
    console.log(response.type);
    console.log(response.url);
});

回應類型

當我們提出擷取要求時,回應會獲得 response.typebasic」, 「cors」或 「opaque」。 這些types會顯示資源的來源,您可以使用這些資源 判斷如何處理回應物件

如果瀏覽器要求相同來源的資源,回應會包含 basic 類型,限制您可以在回應中查看的內容。

如果對另一個來源的資源發出要求,且該來源會傳回 COR 標頭,則類型為 corscors 回應類似於 basic 回應,但會限制 可查看「Cache-Control」、「Content-Language」、「Content-Type」、「Expires」和 Last-ModifiedPragma

opaque 回應來自未傳回 CORS 的不同來源 標題。如果得到不透明回應, 讀取傳回的資料或查看要求狀態,也就是說 以及要求是否成功

您可以為擷取要求定義模式,藉此只讓某些要求類型 解析。您可以設定的模式如下:

  • same-origin 只會成功針對相同來源的資產發出要求,且 也會拒絕所有其他要求。
  • cors 允許要求相同來源及其他來源的資產 會傳回適當的 COR 標頭。
  • cors-with-forced-preflight 會執行預檢 查看 再提出要求
  • no-cors 的用途是向其他沒有 CORS 的來源發出要求 標頭並產生 opaque 回應,但如 所述,這並非 都可以使用這項工具

如要定義模式,請將選項物件新增為 fetch 要求,然後定義該物件中的模式:

fetch('http://some-site.com/cors-enabled/some.json', {mode: 'cors'})
    .then(function(response) {
    return response.text();
    })
    .then(function(text) {
    console.log('Request successful', text);
    })
    .catch(function(error) {
    log('Request failed', error)
    });

Promise 鏈結

實現承諾的一大特色是能夠鏈結在一起。適用對象 fetch(),可讓您跨擷取要求共用邏輯。

如果您使用的是 JSON API,必須檢查狀態並剖析 每個回應的 JSON。若要簡化程式碼,可以定義狀態和 JSON 會在傳回承諾的單獨函式中剖析,並使用擷取作業 要求僅處理最終資料和錯誤情況。

function status(response) {
    if (response.status >= 200 && response.status < 300) {
    return Promise.resolve(response)
    } else {
    return Promise.reject(new Error(response.statusText))
    }
}

function json(response) {
    return response.json()
}

fetch('users.json')
    .then(status)
    .then(json)
    .then(function(data) {
    console.log('Request succeeded with JSON response', data);
    }).catch(function(error) {
    console.log('Request failed', error);
    });

這個範例會定義 status 函式,以便檢查 response.status 和 會傳回已解析的 Promise Promise.resolve()、 或已遭拒的承諾使用名稱 Promise.reject()。 這是 fetch() 鏈結中呼叫的第一個方法。

如果 Promise 已解析,指令碼會呼叫 json() 方法, 從 response.json() 呼叫傳回第二個 Promise,並 物件,當中含有剖析 JSON 檔案。如果剖析失敗,Promise 就會是 且 include 陳述式會執行

這個結構可讓您在所有擷取要求中共用邏輯, 維護、讀取及測試程式碼變得更簡單

POST 要求

有時候,網頁應用程式需要使用 POST 方法呼叫 API,並加入一些 參數中。方法是設定 methodbody fetch()選項中的參數:

fetch(url, {
    method: 'post',
    headers: {
        "Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
    },
    body: 'foo=bar&lorem=ipsum'
    })
    .then(json)
    .then(function (data) {
    console.log('Request succeeded with JSON response', data);
    })
    .catch(function (error) {
    console.log('Request failed', error);
    });

透過擷取要求傳送憑證

如要透過 Cookie 等憑證提出擷取要求,請設定要求的 將 credentials 的值設為 "include"

fetch(url, {
    credentials: 'include'
})