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配置
-
- 默认开启,可配置关闭
- 统一管理,业务中可以不用再去关心这个逻辑
- 支持自动取消重复的请求
代码链接
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)
TanStack Query 是一种流行的前端数据获取库,通常用于管理异步数据。它是由 Tanner Linsley 创建的 TanStack 生态系统的一部分。
该库包括 React Query 和 Vue Query,这两个库分别是为 React 和 Vue.js 应用程序设计的。
使用这些库,开发人员可以更容易地处理应用程序中的服务器状态,包括缓存、同步、后台更新和垃圾收集等功能。
这些函数使得处理远程数据变得更加简单,同时也大大提升了应用程序的性能。
概括来说,TanStack Query 提供了一种对异步数据进行更高级管理的方式,它提供的功能远超过普通的 HTTP 请求客户端(例如 axios 或 fetch)。
不是axios的替代品,是帮助我们更舒服的使用axios
vue-query
简介
提供了用于在 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的一些功能还需要手动进行封装。