fetch() 简介

Matt Gaunt

fetch() 用于发出类似于 XMLHttpRequest (XHR) 的网络请求。通过 主要区别在于,Fetch API 使用的是 Promise,它具有 更简单的 API,可帮助您避免 XMLHttpRequest API。

浏览器支持

  • Chrome:42。 <ph type="x-smartling-placeholder">
  • Edge:14。 <ph type="x-smartling-placeholder">
  • Firefox:39。 <ph type="x-smartling-placeholder">
  • Safari:10.1. <ph type="x-smartling-placeholder">

来源

如果您从未使用过 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.type 的“basic”, “cors”或 “opaque”。 这些types显示了资源的来源,您可以使用它们 确定如何处理响应对象。

当浏览器请求同源上的资源时,响应将包含一个 basic 类型,限制了您可以从响应中查看的内容。

如果针对另一来源上的资源发出请求,且该来源返回 CORs 标头,则类型为 corscors 响应与 basic 响应类似,但它们会限制 可以查看 Cache-ControlContent-LanguageContent-TypeExpiresLast-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 链

promise 的一大特色是能够将它们链接在一起。对于 fetch(),这样可让您在多个提取请求之间共享逻辑。

如果您使用的是 JSON API,则需要检查状态并解析 每个响应的 JSON 代码。您可以通过定义状态和 在返回 promise 的单独函数中进行 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,如下所示: Promise.reject()。 这是 fetch() 链中调用的第一个方法。

如果 Promise 解析,脚本便会调用 json() 方法, 从 response.json() 调用返回第二个 Promise 并创建一个 包含已解析的 JSON 的对象。如果解析失败,则 promise 然后会执行 catch 语句。

这种结构可让您在所有提取请求之间共享该逻辑, 使代码更易于维护、阅读和测试。

POST 请求

有时,Web 应用需要使用 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'
})