Fetch API基于Promise封装的Http请求接口

fetch接口是用来解决Ajax(xhr)在写法和调用上的不合理和开放的js接口,已经在很多项目上使用,运行良好,取代ajax也只是时间问题,虽然fetch还有一些功能不全面但是使用上已经没有什么问题,所以我写下来记录一下自己的学习

两者对比

Ajax请求

var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'json';

xhr.onload = function() {
  console.log(xhr.response);
};

xhr.onerror = function() {
  console.log("Oops, error");
};

xhr.send();

fetch请求

fetch(url).then(function(response) {
  return response.json();
}).then(function(data) {
  console.log(data);
}).catch(function(e) {
  console.log("Oops, error");
});

从上面就可以看出来ajax请求将各个方法都分开写,不直观用起来也很麻烦,还需要写一些兼容性的代码,同时对ajax的封装可能会用到回调函数。fetch方法更为简单,基本和promise的用法相同,流程是线性的,且不用考虑回调问题。


兼容性

Fetch API基于Promise封装的Http请求接口

fetch已经兼容大部分浏览器,ie8以上需要使用polyfill做兼容,ie8以下的版本就别考虑了。fetch接口以及在很多的项目上使用,国外的项目使用fetch以及成为一个惯例,国内阿里也将fetch用在很多项目上,使用上没有任何问题,ant design pro上的请求方法也是在对fetch的封装(ps:上一篇博客,有写我怎么修改原来封装的request函数),所以开始使用fetch吧,已经没有什么好顾虑的了。


使用fetch

现来一个完整的fetch,每个属性干嘛用的一些先简单写在注释里

fetch('http://www.demo.com/demo',
//下面是http请求的配置项,根据自己的实际接口来写
{
    body: JSON.stringify(data), // 发送的数据
    cache: 'no-cache', // 设置 cache 模式 *default, no-cache, reload, force-cache, only-if-cached
    credentials: 'same-origin', // 是否需要包含cookie  include(包含), same-origin(同源), omit(不包含|默认)  因为默认是不包含的 所以如果你要发送cookie加必须写include
    //请求头,可以用 Header对象的实例来设置
    headers: {
      'user-agent': 'Mozilla/4.0 MDN Example',
      'content-type': 'application/json'
    },
    method: 'POST', // 请求方式,GET, POST, PUT, DELETE, etc.
    mode: 'cors', //是否cors跨域 no-cors, cors, *same-origin 
    redirect: 'follow', // manual, *follow, error
    referrer: 'no-referrer', // *client, no-referrer
}
)
  .then(function(response) {
  //response并不是直接的返回数据,而是一个Response对象的实例,要获取数据用json(),下面会介绍
    return response.json();
  })
  .then(function(myJson) {
    console.log(myJson);
  });

看起来是不是很简单 ,上面的一个例子就把fetch的使用说清楚了,但是要完全使用还要需要了解Headers对象和Response对象,下面介绍这两个


Headers (这个感觉用处不算特别大,也可以跳过直接用)

Headers就是为了设置header属性的,相较于上面的直接写一个对象的方式,Headers可以使用guard属性控制Header是否可读,可修改等。现来看下Headers怎么用:

通过append添加元素

var headers = new Headers();
reqHeaders.append("Content-Type", "text/plain"
reqHeaders.append("X-Custom-Header", "ProcessThisImmediately"); 

直接传入构造函数

`reqHeaders = new Headers({  "Content-Type": "text/plain",  "Content-Length": content.length.toString(),  "X-Custom-Header": "ProcessThisImmediately",});`

修改对象

console.log(reqHeaders.has("Content-Type")); // true
console.log(reqHeaders.has("Set-Cookie")); // false
reqHeaders.set("Content-Type", "text/html");
reqHeaders.append("X-Custom-Header", "AnotherValue");
 
console.log(reqHeaders.get("Content-Length")); // 11
console.log(reqHeaders.getAll("X-Custom-Header")); // ["ProcessThisImmediately", "AnotherValue"]
 
reqHeaders.delete("X-Custom-Header");
console.log(reqHeaders.getAll("X-Custom-Header")); // []

然后介绍一下Headers存在最主要的意义就是有一个guard属性,控制Header对象是否可以被操作,有以下值

  • "none":默认值
  • "request"Request.headers 对象只读
  • "request-no-cors":在 no-cors 模式下,Request.headers 对象只读
  • "response"Response.headers 对象只读
  • "immutable":通常在 ServiceWorkers 中使用,所有 Header 对象都为只读

Response对象

之前就说过了,fetch的then中返回的不是一个字面量对象,而是一个Response对象的实例,返回的实例可用以下方法,分别处理数据

  • arrayBuffer() 获取ArrayBuffer格式的promise对象
  • blob() 获取Bolb格式的promise对象
  • json() -获取字符串对象
  • text()获取json的promise对象
  • formData() 获取formData格式的promise对象

还有主要的属性(其他属性自己看)
Response文档

  • Response.status包含Response的状态码 (例如, 200 成功).,网络的状态码

  • Response.ok包含了一个布尔值来标示该Response成功(状态码200-299) 还是失败.

  • Response.url包含Response的URL.


总结

其他基本上就没什么了,基本上看完就能直接用了,fetch的api本身就很简单,形式也和promise一样,所以也很习惯使用,唯一还有不足的就是没用abortcancel等方法可以中断请求,也没有isRejectedisResolved方法可以获取状态,也没finally,always等方法,但是对于普通的使用不没有大影响,日后fetch也会进一步完善。对于fetch的使用也需要进一步封装,最好是封装成async函数的方式,异步流程更好控制,这些在一些现成的框架上也有写好的方法可以学习一下,链接在下面