yuanyuanbyte / Blog

圆圆的博客,预计写七个系列:JavaScript深入系列、JavaScript专题系列、网络系列、Webpack系列、Vue系列、JavaScript基础系列、HTML&CSS应知应会系列。
306 stars 125 forks source link

JavaScript 专题系列之 Ajax、Axios 与 Fetch 的对比 #106

Open yuanyuanbyte opened 2 years ago

yuanyuanbyte commented 2 years ago

本系列的主题是 JavaScript 专题,每期讲解一个技术要点。如果你还不了解各系列内容,文末点击查看全部文章,点我跳转到文末

如果觉得本系列不错,欢迎 Star,你的支持是我创作分享的最大动力。

对比 Ajax、Axios 与 Fetch

Ajax

使用Ajax请求数据一般是这样:

// 1.创建 XMLHttpRequest 对象
var xhr = new XMLHttpRequest();
// 2.设置状态监听函数
xhr.onreadystatechange = function () {// 状态发生变化时,触发回调函数
    if (xhr.readyState !== 4) return;
    if (xhr.status === 200) {
        // 成功:从服务器获取数据,通过responseText拿到响应的文本
        console.log(xhr.responseText)
        // do what
    } else {
        // 失败,根据响应码判断失败原因
        new Error(xhr.statusText)
    }
};
// 3.规定请求的类型、URL 以及是否异步处理请求
xhr.open("GET", url, true);
// 4.将请求发送到服务器
xhr.send();

Axios 和 Fetch 对比

火热程度

虽然无法进行直观的比较,但是我们可以从npm包下载量来看:

在这里插入图片描述

因为Node环境下默认是不支持Fetch的,所以必须要使用node-fetch这个包,而这个包的周下载量一路攀升,可以看到已经来到了每周2千六百多万的下载量。这还仅仅是Node环境下,浏览器则是默认支持不需要第三方包。

在这里插入图片描述

上面是Axios的下载量,可以看到也是一路攀升,Axios封装的各种方法确实非常的好用。

兼容性问题

Axios可以兼容IE浏览器,而Fetch在IE浏览器和一些老版本浏览器上没有受到支持,但是有一个库可以让老版本浏览器支持Fetch即它就是whatwg-fetch,它可以让你在老版本的浏览器中也可以使用Fetch,并且现在很多网站的开发都为了减少成本而选择不再兼容IE浏览器。

请求方式

来看一下如何使用Axios和Fetch进行请求。

Axios:

const options = {
  url: "http://example.com/",
  method: "POST",
  headers: {
    Accept: "application/json",
    "Content-Type": "application/json;charset=UTF-8",
  },
  data: {
    a: 10,
    b: 20,
  },
};

axios(options).then((response) => {
  console.log(response.status);
});

Fetch:

const url = "http://example.com/";
const options = {
  method: "POST",
  headers: {
    Accept: "application/json",
    "Content-Type": "application/json;charset=UTF-8",
  },
  body: JSON.stringify({
    a: 10,
    b: 20,
  }),
};

fetch(url, options).then((response) => {
  console.log(response.status);
});

其中最大的不同之处在于传递数据的方式不同,Axios是放到data属性里,以对象的方式进行传递,而Fetch则是需要放在body属性中,以字符串的方式进行传递。

响应超时

Axios的相应超时设置是非常简单的,直接设置timeout属性就可以了,而Fetch设置起来就远比Axios麻烦,这也是很多人更喜欢Axios而不太喜欢Fetch的原因之一。

axios({
  method: "post",
  url: "http://example.com/",
  timeout: 4000, // 请求4秒无响应则会超时
  data: {
    firstName: "David",
    lastName: "Pollock",
  },
})
  .then((response) => {
    /* 处理响应 */
  })
  .catch((error) => console.error("请求超时"));

Fetch提供了AbortController属性,但是使用起来不像Axios那么简单。

const controller = new AbortController();

const options = {
  method: "POST",
  signal: controller.signal,
  body: JSON.stringify({
    firstName: "David",
    lastName: "Pollock",
  }),
};
const promise = fetch("http://example.com/", options);

// 如果4秒钟没有响应则超时
const timeoutId = setTimeout(() => controller.abort(), 4000);

promise
  .then((response) => {
    /* 处理响应 */
  })
  .catch((error) => console.error("请求超时"));

响应数据的转化

Axios还有非常好的一点就是会自动对数据进行转换,而Fetch则不同,它需要开发者手动转化。

// axios
axios.get("http://example.com/").then(
  (response) => {
    console.log(response.data);
  },
  (error) => {
    console.log(error);
  }
);

// fetch
fetch("http://example.com/")
  .then((response) => response.json()) // 使用response.json()方法 将返回的文本数据解析为JSON数据 以供使用
  .then((data) => {
    console.log(data);
  })
  .catch((error) => console.error(error));

使用Fetch时你需要清楚请求后的数据类型是什么,然后再用对应的方法将它进行转换。

HTTP拦截器

Axios的一大卖点就是它提供了拦截器,可以统一对请求或响应进行一些处理,相信如果看过一个比较完整的项目的请求封装的话,一定对Axios的拦截器有一定的了解,它是一个非常重要的功能。

使用它可以为请求附加token、为请求增加时间戳防止请求缓存,以及拦截响应,一旦状态码不符合预期则直接将响应消息通过弹框的形式展示在界面上,比如密码错误、服务器内部错误、表单验证不通过等问题。

下面章节详细讲解Axios拦截器的配置与使用!

而Fetch没有拦截器功能,但是要实现该功能并不难,直接重写全局Fetch方法就可以办到。

多个并发请求

在项目中大量数据反显会用到 多个并发请求

Axios:

axios
  .all([
    axios.get("https://api.github.com/users/iliakan"),
    axios.get("https://api.github.com/users/taylorotwell"),
  ])
  .then(
    axios.spread((obj1, obj2) => {
      ...
    })
  );

Fetch:

Promise.all([
  fetch("https://api.github.com/users/iliakan"),
  fetch("https://api.github.com/users/taylorotwell"),
])
  .then(async ([res1, res2]) => {
    const a = await res1.json();
    const b = await res2.json();
  })
  .catch((error) => {
    console.log(error);
  });

浏览器原生支持

Fetch碾压Axios的一点就是现代浏览器的原生支持。

不像Axios需要引入一个包,而且需要即时测试某些接口直接在Chrome浏览器中使用Fetch进行请求,尤其是编写爬虫或脚本的时候,你在当前网页打开Chrome的控制台使用Fetch几乎不需要什么配置就可以直接进行请求。

小结

总的来说,现阶段来看 Axios比Fetch好用,Axios使用体验确实优于Fetch。

那么为什么目前在很多大公司的网站上面都开始使用Fetch进行网络请求呢?

结论:在浏览器原生支持上,Fetch优势明显。

参考

查看全部文章

博文系列目录

交流

各系列文章汇总:https://github.com/yuanyuanbyte/Blog

我是圆圆,一名深耕于前端开发的攻城狮。

weixin