Blog icon indicating copy to clipboard operation
Blog copied to clipboard

Fetch

Open shenxuxiang opened this issue 6 years ago • 0 comments

Fetch

在开发过程中,我们向服务端发送请求,一般会使用三种方式, XMLHttpRequest(XHR),Fetch ,jQuery实现的AJAX。其中, XMLHttpRequest(XHR)和Fetch是浏览器的原生API,它们都是全局的方法。jquery的ajax其实是封装了XHR。接下来我们来看看Fetch如何使用。

写在前面

  • Fetch 是基于 Promise 实现的,所以它的返回值是一个 Promise 对象。当请求返回一个代表错误的 HTTP 状态码时,从 fetch() 返回的 Promise 不会被标记为 reject, 即使该 HTTP 响应的状态码是 404500。相反,它会将 Promise 状态标记为 resolve (但是会将 resolve 的返回值的 ok 属性设置为 false ),仅当网络故障时或请求被阻止时,才会标记为 reject

  • 默认情况下,fetch 不会从服务端发送或接收任何 cookies, 如果站点依赖于用户 session,则会导致未经认证的请求(要发送 cookies,必须设置 credentials 选项)。

兼容性

image

isomorphic-fetch

需要支持的话,我们可以在项目中引入isomorphic-fetch,isomorphic-fetch 是对 whatwg-fetch和node-fetch的一种封装,你一份代码就可以在两种环境下跑起来了。

fetch()的使用

第一个参数是一个请求的url。第二个参数是一个可选参数,可以控制不同配置的 init 对象。方法返回一个 promise 对象。

init 对象有哪些属性

  • method — GET, POST, PUT, DELETE, HEADER…
  • headers — 请求头
  • body — 传递给服务器的数据,可以是String/Buffer/Blob/FormData,如果方法是 GET/HEAD,则不能有此参数
  • mode — cors / no-cors / same-origin, 是否跨域,默认是 no-cors
  • credentials — omit / same-origin / include, 是否携带cookie
  • cache — default / no-store / reload / no-cache / force-cache / only-if-cached, 是否使用缓存

如果要在请求中携带凭据,请添加credentials: 'include'。如果你只想在请求URL与调用脚本位于同一起源处时发送凭据(cookie),请添加credentials: 'same-origin'。要确保浏览器不在请求中包含凭据,请使用 credentials: 'omit',这个也是默认值

返回的response有哪些属性

  • status(number): HTTP返回的状态码,范围在100-599之间
  • statusText(String): 服务器返回的状态文字描述
  • ok(Boolean): 如果状态码是以2开头的,则为true
  • headers({}): HTTP请求返回头
  • body: 返回体,这里有处理返回体的一些方法
    • text(): 将返回体处理成字符串类型
    • json(): 返回结果和 JSON.parse(responseText)一样
    • blob(): 返回一个Blob,Blob对象是一个不可更改的类文件的二进制数据
    • arrayBuffer()
    • formData()

用途

文件上传

  var formData = new FormData();
  var photos = document.querySelector("input[type='file'][multiple]");

  formData.append('title', 'My Vegas Vacation');
  // 注意这里上传的是多个文件
  formData.append('photos', photos.files);

  fetch(url, {
    method: 'POST',
    body: formData
  })
    .then(response => {
      if (response.ok) {
        return response.json();
      }
      throw 'the qequest failed';
    })
    .then(response => console.log('Success:', response))
    .catch(error => console.error('Error:', error));

文件下载

  fetch(url, {
    method: 'POST',
    body: JSON.stringify(query),
  })
    .then(response => {
      if (response.ok) {
        return response.blob();
      }
      throw 'the qequest failed';
    })
    .then(data => {
        const blobURL = window.URL.createObjectURL(data);
        download(blobURL);
    })
    .catch(error => console.error('Error:', error));

  function download(url) {
    const a = document.createElement('a');
    a.style.display = 'none';
    a.download = '<文件名>';
    a.href = url;
    a.click();
    document.body.appendChild(a);
    document.body.removeChild(a);
  }

最后

  • 由于 fetch 的兼容性较差,所以不得不使用第三方插件,这里推荐 isomorphic-fetch
  • 不支持progress事件
  • 默认不带cookie
  • 不支持timeout处理
  • 默认不使用数据缓存
  • 错误的 http 状态下如400 | 500等不会 reject,相反它会被 resolve

shenxuxiang avatar May 05 '19 09:05 shenxuxiang