ajax
请求jquery
封装好的ajax
请求fetch
发起请求axios
请求angular
中自带的HttpClient
就目前前端框架开发中来说我们在开发vue
、react
的时候一般都是使用fetch
或axios
自己封装一层来与后端数据交互,至于angular
肯定是用自带的HttpClient
请求方式,但是依然存在几个致命的弱点,
ajax
请求📢 针对同一个接口发起多次请求的解决方法,目前常见的解决方案
axios
的取消发起请求,参考文档vue
中还没看到比较好的方法rect
中可以借用类似react-query工具对请求包装一层angular
中直接使用rxjs
的操作符shareReplay
RTK不仅帮助我们解决了state的问题,同时,它还为我们提供了RTK Query用来帮助我们处理数据加载的问题。RTK Query是一个强大的数据获取和缓存工具。在它的帮助下,Web应用中的加载变得十分简单,它使我们不再需要自己编写获取数据和缓存数据的逻辑。
rtk-query
是redux-toolkit
里面的一个分之,专门用来优化前端接口请求,目前也只支持在react
中使用。
RTK Query 是一个强大的数据获取和缓存工具。它旨在简化在 Web 应用程序中加载数据的常见情况,无需自己手动编写数据获取和缓存逻辑。
RTK Query 是一个包含在 Redux Toolkit 包中的可选插件,其功能构建在 Redux Toolkit 中的其他 API 之上。
Web应用中加载数据时需要处理的问题:
这些问题,RTKQ都可以帮助我们处理。首先,可以直接通过RTKQ向服务器发送请求加载数据,并且RTKQ会自动对数据进行缓存,避免重复发送不必要的请求。其次,RTKQ在发送请求时会根据请求不同的状态返回不同的值,我们可以通过这些值来监视请求发送的过程并随时中止。
我们将 createAsyncThunk
与 createSlice
一起使用,在发出请求和管理加载状态方面仍然需要进行大量手动工作。我们必须创建异步 thunk,发出实际请求,从响应中提取相关字段,添加加载状态字段,在 extraReducers
中添加处理程序以处理 pending/fulfilled/rejected
情况,并实际编写正确的状态更新。
在过去的几年里,React 社区已经意识到 “数据获取和缓存” 实际上是一组不同于 “状态管理” 的关注点。虽然你可以使用 Redux 之类的状态管理库来缓存数据,但用例差异较大,因此值得使用专门为数据获取用例构建的工具。
RTK Query 在其 API 设计中添加了独特的方法:
createSlice
和 createAsyncThunk
API 之上data
和 isFetching
字段,并在组件挂载和卸载时管理缓存数据的生命周期📢
rtk-query
的使用环境,必须是react
版本大于 17,可以使用hooks
的版本,因为使用rtk-query
的查询都是hooks
的方式,如果你项目简单redux
都未使用到,本人不建议你用rtk-query
,可能直接使用axios
请求更加的简单方便。
后面这些案例后端接口返回格式都是
{ "code":200, "data":[] }
- 1
- 2
- 3
- 4
- 5
使用 RTK Query,管理缓存数据的逻辑被集中到每个应用程序的单个“API Slice”中。就像每个应用程序只有一个 Redux 存储一样,我们现在有一个Slice 用于 所有 我们的缓存数据。
我们将从定义一个新的 sudentApiSlice.js
文件开始。由于这不是特定于我们已经编写的任何其他“功能”,我们将添加一个新的 features/api/
文件夹并将 sudentApiSlice.js
放在那里。让我们填写 API Slice 文件,然后分解里面的代码,看看它在做什么:
features/api/sudentApiSlice.js
// 从特定于 React 的入口点导入 RTK Query 方法
import {
createApi, fetchBaseQuery } from '@reduxjs/toolkit/dist/query/react'
// 上面这个引入的会自动创建钩子
// import { createApi } from '@reduxjs/toolkit/query'
// 定义我们的单个 API Slice 对象
//createApi() 用来创建RTKQ中的API对象
// RTKQ的所有功能都需要通过该对象来进行
// createApi() 需要一个对象作为参数
export const sudentApiSlice = createApi({
reducerPath: 'studentApi', // Api的标识,不能和其他的Api或reducer重复
// 指定查询的基础信息,发送请求使用的工具
baseQuery: fetchBaseQuery({
// 我们所有的请求都有以 “/api 开头的 URL
baseUrl: 'http://localhost:8080/api',
}),
// “endpoints” 代表对该服务器的操作和请求
endpoints: builder => ({
// `getStudents` endpoint 是一个返回数据的 “Query” 操作
getStudents: builder.query({
// 请求的 URL 是“/api/all/student”
query: () => '/all/student',
}),
}),
})
// Api对象创建后,对象中会根据各种方法自动的生成对应的钩子函数
// 通过这些钩子函数,可以来向服务器发送请求
// 钩子函数的命名规则 getStudents --> useGetStudentsQuery
export const {
useGetStudentsQuery } = sudentApiSlice
上例是一个比较简单的Api对象的例子,我们来分析一下,首先我们需要调用createApi()
来创建Api对象。这个方法在RTK中存在两个版本,一个位于@reduxjs/toolkit/dist/query
下,一个位于@reduxjs/toolkit/dist/query/react
下。react目录下的版本会自动生成一个钩子,方便我们使用Api。如果不要钩子,可以引入query下的版本,当然我不建议你这么做。
createApi()
需要一个配置对象作为参数,配置对象中的属性繁多,我们暂时介绍案例中用到的属性:
reducerPath
用来设置reducer的唯一标识,主要用来在创建store时指定action的type属性,如果不指定默认为api。
baseQuery
用来设置发送请求的工具,就是你是用什么发请求,RTKQ为我们提供了fetchBaseQuery作为查询工具,它对fetch进行了简单的封装,很方便,如果你不喜欢可以改用其他工具,这里暂时不做讨论。
fetchBaseQuery
简单封装过的fetch调用后会返回一个封装后的工具函数。需要一个配置对象作为参数,baseUrl表示Api请求的基本路径,指定后请求将会以该路径为基本路径。配置对象中其他属性暂不讨论。
endpoints
Api对象封装了一类功能,比如学生的增删改查,我们会统一封装到一个对象中。一类功能中的每一个具体功能我们可以称它是一个端点。endpoints用来对请求中的端点进行配置。
endpoints是一个回调函数,可以用普通方法的形式指定,也可以用箭头函数。回调函数中会收到一个build对象,使用build对象对点进行映射。回调函数的返回值是一个对象,Api对象中的所有端点都要在该对象中进行配置。
对象中属性名就是要实现的功能名,比如获取所有学生可以命名为getStudents,根据id获取学生可以命名为getStudentById。属性值要通过build对象创建,分两种情况:
查询:build.query({})
增删改:build.mutation({})
例如:
getStudents: builder.query({
// 请求的 URL 是“/api/all/student”
query: () => '/all/student',
}),
先说query,query也需要一个配置对象作为参数。配置对象里同样有n多个属性,现在直说一个,query方法。注意不要搞混两个query,一个是build的query方法,一个是query方法配置对象中的属性,这个方法需要返回一个子路径,这个子路径将会和baseUrl拼接为一个完整的请求路径。比如:getStudets的最终请求地址是:
http://localhost:8080/api + /all/student = http://localhost:8080/api/all/student
可算是介绍完了,但是注意了这个只是最基本的配置。RTKQ功能非常强大,但是配置也比较麻烦。不过,熟了就好了。
上例中,我们创建一个Api对象studentApi,并且在对象中定义了一个getStudents方法用来查询所有的学生信息。如果我们使用react下的createApi,则其创建的Api对象中会自动生成钩子函数,钩子函数名字为useXxxQuery或useXxxMutation,中间的Xxx就是方法名,查询方法的后缀为Query,修改方法的后缀为Mutation。所以上例中,Api对象中会自动生成一个名为useGetStudentsQuery的钩子,我们可以获取并将钩子向外部暴露。
export const {
useGetStudentsQuery} = studentApi;
我们现在需要将 API Slice 连接到我们的 Redux 存储。我们可以修改现有的 store.js
文件,将 API slice 的 cache reducer 添加到状态中。此外,API slice 会生成需要添加到 store 的自定义 middleware。这个 middleware 必须 被添加——它管理缓存的生命周期和控制是否过期。
store/index.js
import {
configureStore } from '@reduxjs/toolkit'
import {
sudentApiSlice } from './features/api/sudentApiSlice'
// configureStore创建一个redux数据
const store = configureStore({