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...

相关推荐
还是大剑师兰特29 分钟前
D3的竞品有哪些,D3的优势,D3和echarts的对比
前端·javascript·echarts
王解29 分钟前
【深度解析】CSS工程化全攻略(1)
前端·css
一只小白菜~35 分钟前
web浏览器环境下使用window.open()打开PDF文件不是预览,而是下载文件?
前端·javascript·pdf·windowopen预览pdf
方才coding40 分钟前
1小时构建Vue3知识体系之vue的生命周期函数
前端·javascript·vue.js
阿征学IT1 小时前
vue过滤器初步使用
前端·javascript·vue.js
王哲晓1 小时前
第四十五章 Vue之Vuex模块化创建(module)
前端·javascript·vue.js
丶21361 小时前
【WEB】深入理解 CORS(跨域资源共享):原理、配置与常见问题
前端·架构·web
发现你走远了1 小时前
『VUE』25. 组件事件与v-model(详细图文注释)
前端·javascript·vue.js
Mr.咕咕1 小时前
Django 搭建数据管理web——商品管理
前端·python·django
张张打怪兽1 小时前
css-50 Projects in 50 Days(3)
前端·css