Ajax、Fetch和Axios:前端异步请求的比较与选择

Ajax

全称是Asynchronous JavaScript And XML [e'sɪŋkrənəs]

Ajax 异步网络请求,是一项标准,是为了能在不更新整个页面的前提下修改维护数据

实现Ajax的方式很多。

  • 原生的XHR

    • 1999年提出,距今已经24年

    XHR was an ugly baby and time has not been kind to it. It's 16 now. In a few years it'll be old enough to drink, and it's enough of a pain in the arse when it's sober

    • 是浏览器提供API
    • 配置调用繁琐,心智负担较重
    • 观察如下代码,代码组织不够语义化,很容易陷入回调地狱
js 复制代码
const xhr = new XMLHttpRequest()
xhr.onreadystatechange = () => {
    if (xhr.readystate == 4) {
        if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
            alert(xhr.responseText)
        } else {
            alert("Request was unsuccessful: " + xhr.status)
        }
    }
}
xhr.open("get", "example.php", true)
xhr.send(null)
  • jquery 封装的 ajax

    • $.ajax() 2011年提出
    • 没有必要因为使用ajax而引用jquery
  • axios
    • 2014年发布第一个版本

aixos

简介

axios 是一个基于promise的HTTP库,可以用在浏览器和node.js中

特性

  • 从浏览器中创建 XMLHttpRequests => 适配器

  • 从 node.js 创建 http 请求 => node的http库

  • 支持 Promise API => axios 内部返回的就是一个promise

  • 拦截请求和响应 => interceptors 拦截器

  • 转换请求数据和响应数据=>转换器

  • 取消请求 => 基于AbortController

    • 中止一个尚未完成的 Web(网络)请求。
  • 自动转换 JSON 数据 => 根据content-type 自动将请求数据对象转为json
  • 客户端支持防御 XSRF => 可设置请求头部

封装

封装目的

  • 降低心智负担
  • 减少冗余代码
  • 使用更加高效

封装思路

  • 正常请求基础的配置,比如超时配置,baseUrl,跨域携带cookie等等
  • 响应拦截处理
    • 请求成功,业务状态码成功,直接解析接口中的data,不用一层一层再去取code,判断,拿结果
    • 请求成功,业务状态码不成功,可以选择自己处理特殊状态码,也可以选择全局 message 提示服务端的报错,业务开发中,大部分都是直接提示服务端报错,但是也有需要前端处理状态码的逻辑
    • 请求失败,全局 message 提示报错
    • 统一的特殊请求码处理,或者状态码做特殊逻辑,比如丢失登陆态,请求参数有误等等
  • 全局统一的loading配置
    • 默认开启,可配置关闭
    • 统一管理,业务中可以不用再去关心这个逻辑
  • 支持自动取消重复的请求

代码链接

github.com/Yinzhuo1997...

fetch

2011年提出,2015年正式标准化

fetch 和 axios 没有任何关系,不是同一层级的东西

fetch确实是xhr内部演进的结果。

node17.5 已经合并了 fetch API

对比

设计理念

  • 分离 request / response / header / body,更加灵活
    • 比如可以客户端返回response,不通过网络。结合缓存做一些优化处理。
js 复制代码
self.addEventListener('fetch', function (event) {
  if (event.request.url === new URL('/', location).href) {
    event.respondWith(
      new Response('<h1>Hello!</h1>', {
        headers: {'Content-Type', 'text/html'}
      })
    )
  }
})
  • fetch方法天然返回Promsie对象
js 复制代码
async function get(url){
  let response = await fetch(url);
  console.info('Url - fetched');	
  console.log(response);				
}
console.log('Start Fetch URL');	
get('test.json');	
console.log('Todo anysc next');		

争议

  • 标准的更新应该是迭代式的
  • 认为 fetch API 对于某些 http 错误码不会 reject(比如 400、500等)仅在发生"network error(网络错误)"才会reject
    • 到底合不合理?不管是错误码还是正确码都表示 http 客户端有接受到服务器的 response,而网络错误这类才真正代表着异常。
  • 缺少中断请求,超时取消请求
    • 需要使用创建一个新的AbortController对象,来取消请求,这个对象中有一个signal属性,将signal传入fetch请求的配置中,然后我们使用AbortController的abort方法可取消此次请求。
    • 这一点与axios 现在已经一致
  • 方法无法跟踪 上传 进度

兼容性

  • 权衡,兼容性对你是否及其重要
  • whatwg-fetch fetch API 的 polyfill

除了兼容性,还有什么遏制了 fetch API 替代了 XHR ?

那是因为各种优秀的库(XHR 封装)基本能够满足上层应用者大部分的功能需求,并且也没有特别大的缺点,那么为什么还要冒着风险使用新的 fetch API 呢?这是不是也体现了你已经默默做了技术选择的 tradeoff 呢?

尽管有种种的问题,但是 fetch API 的未来仍然是光明的,npm 的 polyfill 包下载量也能简单的说明问题:

  • 下载量
    • axios 45,935,428
    • whatwg-fetch 12,486,089

两者的差距也并不是太远

TanStack Query (曾用名:React Query)

github.com/TanStack/qu...

TanStack Query 是一种流行的前端数据获取库,通常用于管理异步数据。它是由 Tanner Linsley 创建的 TanStack 生态系统的一部分。

该库包括 React Query 和 Vue Query,这两个库分别是为 React 和 Vue.js 应用程序设计的。

使用这些库,开发人员可以更容易地处理应用程序中的服务器状态,包括缓存、同步、后台更新和垃圾收集等功能。

这些函数使得处理远程数据变得更加简单,同时也大大提升了应用程序的性能。

概括来说,TanStack Query 提供了一种对异步数据进行更高级管理的方式,它提供的功能远超过普通的 HTTP 请求客户端(例如 axios 或 fetch)。

不是axios的替代品,是帮助我们更舒服的使用axios

vue-query

vue-query.vercel.app/#/

简介

提供了用于在 Vue 中获取、缓存和更新异步数据的钩子

大多数传统的状态管理库非常适合处理客户端状态,但它们不太适合处理异步或服务器状态。

js 复制代码
<script setup>
import { useQuery } from "vue-query";

function useTodosQuery() {
  return useQuery("todos", fetchTodoList);
}

const { isLoading, isError, data, error } = useTodosQuery();
</script>

<template>
  <span v-if="isLoading">Loading...</span>
  <span v-else-if="isError">Error: {{ error.message }}</span>
  <!-- We can assume by this point that `isSuccess === true` -->
  <ul v-else>
    <li v-for="todo in data" :key="todo.id">{{ todo.title }}</li>
  </ul>
</template>

特性

简单易用:"vue-query" 提供了简洁的 API 和 hook,使数据查询和状态管理变得非常简单,减少了样板代码和冗余操作。

数据缓存:"vue-query" 内置了数据缓存机制,自动处理数据缓存,避免重复的网络请求,提高应用性能。

自动状态管理:"vue-query" 自动处理数据加载状态,包括正在加载、加载完成、加载失败等状态,简化了数据加载的处理逻辑。

请求重试:"vue-query" 内置了请求重试机制,可以在网络错误时自动重新尝试请求,提高了数据请求的可靠性。

并发请求:"vue-query" 支持并发请求,可以一次性请求多个数据,提高了数据请求的效率。

优缺点

优点

简化了数据查询和状态管理的复杂性,让开发者能够更轻松地处理数据。

内置了数据缓存和状态管理,提高了应用性能和用户体验。

提供了丰富的功能和配置选项,适用于各种类型的数据查询和状态管理需求。

支持并发请求,提高了数据请求的效率。

社区活跃,持续更新和维护。

缺点

"vue-query" 与其他数据状态管理库(如 Vuex)相比,可能需要一定的学习成本,特别是对于不熟悉 hook 的开发者。

如果应用中只有简单的数据查询需求,可能使用 "vue-query" 会显得有些过于重量级。

总结

两者区别

axios fetch
兼容性问题 兼容IE whatwg-fetch
响应超时 timeout 简单易用 setTimeout + new AbortController()
对数据转化 自动对数据进行转化response.data 手动转化需要清楚请求后的数据类型是什么,然后再用对应的方法将它进行转换。
HTTP拦截器 请求附加token、为请求增加时间戳防止请求缓存,以及拦截响应 Fetch没有拦截器功能,如果需要直接重写全局Fetch方法就可以办到。
浏览器原生支持 不支持 原生支持,无需安装额外的包

我个人的体验来讲,Axios使用体验确实优于Fetch

最大的不同点在于Fetch是浏览器原生支持,而Axios需要引入Axios库,有利于首页js资源控制体积

如果使用Fetch要想实现Axios的一些功能还需要手动进行封装。

参考链接

juejin.cn/post/715472...

juejin.cn/post/684700...
juejin.cn/post/693415...

相关推荐
Darling02zjh25 分钟前
GUI图形化演示
前端
Channing Lewis28 分钟前
如何判断一个网站后端是用什么语言写的
前端·数据库·python
互联网搬砖老肖38 分钟前
Web 架构之状态码全解
前端·架构
showmethetime1 小时前
matlab提取脑电数据的五种频域特征指标数值
前端·人工智能·matlab
码农捻旧1 小时前
解决Mongoose “Cannot overwrite model once compiled“ 错误的完整指南
javascript·数据库·mongodb·node.js·express
淡笑沐白1 小时前
探索Turn.js:打造惊艳的3D翻页效果
javascript·html5·turn.js
sunxunyong2 小时前
yarn任务筛选spark任务,判断内存/CPU使用超过限制任务
javascript·ajax·spark
Ynov2 小时前
详细解释api
javascript·visual studio code
左钦杨2 小时前
IOS CSS3 right transformX 动画卡顿 回弹
前端·ios·css3
NaclarbCSDN2 小时前
Java集合框架
java·开发语言·前端