Fetch简介

Fetch API 提供了一个 JavaScript接口,用于访问和操纵HTTP管道的部分,例如请求和响应。它还提供了一个全局 fetch()方法,该方法提供了一种简单,合乎逻辑的方式来跨网络异步获取资源。

这种功能以前是使用 XMLHttpRequest实现的。Fetch提供了一个更好的替代方法,可以很容易地被其他技术使用,例如 Service Workers。Fetch还提供了单个逻辑位置来定义其他HTTP相关概念,例如 CORS和HTTP的扩展。

Fetch与Ajax区别

  • 当接收到一个代表错误的 HTTP 状态码时,从 fetch()返回的 Promise 不会被标记为 reject, 即使该 HTTP 响应的状态码是 404 或 500。相反,它会将 Promise 状态标记为 resolve (但是会将 resolve 的返回值的 ok 属性设置为 false ), 仅当网络故障时或请求被阻止时,才会标记为 reject。
  • 默认情况下, fetch 不会从服务端发送或接收任何 cookies, 如果站点依赖于用户 session,则会导致未经认证的请求(要发送 cookies,必须设置 credentials 选项).
    如果想要在同域中自动发送cookie,加上 credentials 的 same-origin 选项
fetch(url, {
  credentials: ’same-origin'
})

same-origin值使得fetch处理Cookie与XMLHttpRequest类似。 否则,Cookie将不会被发送,导致这些请求不保留认证会话。
对于CORS请求,使用include值允许将凭据发送到其他域:

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

Why Fetch?

  1. XMLHttpRequest 是一个设计粗糙的 API,不符合关注分离(Separation of Concerns)的原则,配置和调用方式非常混乱,而且基于事件的异步模型写起来也没有现代的 Promise,generator/yield,async/await 友好。
  2. 对于传统的XMLHttpRequest而言,你必须使用它的一个实例来执行请求和检索返回的响应。 但是通过Fetch API,我们还能够明确的配置请求对象。
  3. 同构方便,使用 isomorphic-fetch
    注:同构(isomorphic/universal)就是使前后端运行同一套代码的意思,后端一般是指 NodeJS 环境。

Fetch的缺陷

  1. Fetch的支持性不好,下图为Fetch在各大平台的支持情况。
    Fetch支持性情况
  2. 使用XMLHttpRequest你可以模拟进度(监听progress事件),Fetch无法做到
  3. Fetch 和 Promise 一样,一旦发起,不能中断,也不会超时,只能等待被 resolve 或 reject。

语法说明

fetch(url, options).then(function(response) {
  // handle HTTP response
}, function(error) {
  // handle network error
})
  • url:定义要获取的资源。这可能是:

    • 一个 USVString 字符串,包含要获取资源的 URL。
    • 一个 Request 对象。
  • options(可选):一个配置项对象,包括所有对请求的设置。可选的参数有:

    • method: 请求使用的方法,如 GET、POST。
    • headers: 请求的头信息,形式为 Headers 对象或 ByteString。
    • body: 请求的 body 信息:可能是一个 Blob、BufferSource、FormData、URLSearchParams 或者 USVString 对象。注意 GET 或 HEAD 方法的请求不能包含 body 信息。
    • mode: 请求的模式,如 cors、 no-cors 或者 same-origin。
    • credentials: 请求的 credentials,如 omit、same-origin 或者 include。
    • cache: 请求的 cache 模式: default, no-store, reload, no-cache, force-cache, 或者 only-if-cached。
  • response:一个 Promise,resolve 时回传 Response 对象:

    • 属性:

      • status (number) - HTTP请求结果参数,在100–599 范围
      • statusText (String) - 服务器返回的状态报告
      • ok (boolean) - 如果返回200表示请求成功则为true
      • headers (Headers) - 返回头部信息,下面详细介绍
      • url (String) - 请求的地址
    • 方法:

      • text() - 以string的形式生成请求text
      • json() - 生成JSON.parse(responseText)的结果
      • blob() - 生成一个Blob
      • arrayBuffer() - 生成一个ArrayBuffer
      • formData() - 生成格式化的数据,可用于其他的请求
    • 其他方法:

      • clone()
      • Response.error()
      • Response.redirect()
  • response.headers

    • has(name) (boolean) - 判断是否存在该信息头
    • get(name) (String) - 获取信息头的数据
    • getAll(name) (Array) - 获取所有头部数据
    • set(name, value) - 设置信息头的参数
    • append(name, value) - 添加header的内容
    • delete(name) - 删除header的信息
    • forEach(function(value, name){ ... }, [thisContext]) - 循环读取header的信息

使用实例

var myHeaders = new Headers();
var myInit = { method: 'GET',
               headers: myHeaders,
               mode: 'cors',
               cache: 'default' };
fetch('flowers.jpg',myInit)
.then(function(response) {
  return response.blob();
})
.then(function(myBlob) {
  var objectURL = URL.createObjectURL(myBlob);
  myImage.src = objectURL;
});

也可以自定义请求对象:

var myHeaders = new Headers();
var myInit = { method: 'GET',
               headers: myHeaders,
               mode: 'cors',
               cache: 'default' };

var myRequest = new Request('flowers.jpg', myInit);
fetch(myRequest).then(function(response) {
  return response.blob();
}).then(function(myBlob) {
  var objectURL = URL.createObjectURL(myBlob);
  myImage.src = objectURL;
});

参考资料

MDN 使用 Fetch
SegmentFault Fetch用法说明
Github Fetch