项目所有的请求均存放于 src/api 目录下,且所有的请求都是通过 request 方法发起的,这个方法存放在 src/utils/request 中,内部封装了 [Ky](https://github.com/sindresorhus/ky) 库。
一个经典的目录结构如下:
├── src
│ └── api
│ └── system # 系统管理
│ ├── index.ts # 聚合所有接口
│ └── role # 角色管理
│ ├── index.ts # 角色管理接口
│ └── types.ts # 角色管理接口类型定义
import type { RoleItemType } from "./types";
import { request } from "#src/utils";
export * from "./types";
/* 获取角色列表 */
export function fetchRoleList(data: any) {
return request.get<ApiListResponse<RoleItemType>>("role-list", { searchParams: data, ignoreLoading: true }).json();
}
/* 新增角色 */
export function fetchAddRoleItem(data: RoleItemType) {
return request.post<ApiResponse<string>>("role-item", { json: data, ignoreLoading: true }).json();
}
/* 修改角色 */
export function fetchUpdateRoleItem(data: RoleItemType) {
return request.put<ApiResponse<string>>("role-item", { json: data, ignoreLoading: true }).json();
}
/* 删除角色 */
export function fetchDeleteRoleItem(id: number) {
return request.delete<ApiResponse<string>>("role-item", { json: id, ignoreLoading: true }).json();
}
ignoreLoading 默认值为 false 为 true 时,不显示 loading 加载动画,接口将在后台静默请求。
推荐只在获取数据的时候(即通过 GET 请求的接口)使用 Tanstack Query 进行网络请求。
使用 useEffect 进行网络请求,有几个无法解决的痛点。
强烈建议阅读 How to fetch data with React Hooks 了解如何发送请求以及 Tanstack Query 的原理。
当遇到项目某些请求不需要携带 token 的情况下,可以添加到白名单中,在 src/utils/request/index.ts 文件中设置 requestWhiteList 变量的值:
// 请求白名单, 请求白名单内的接口不需要携带 token
const requestWhiteList = ["/login"];
用户登录之后会返回两个 token,一个用于请求接口验证,一个用于 token 过期无感刷新 token,后端可以通过简单的设置让用户在某一段时间无需再次登录。
代码在 src/utils/request 文件夹中的 refresh.ts 文件中,请查看 refreshTokenAndRetry 函数的代码。
::: info 暂存请求
refreshTokenAndRetry 函数重新刷新 token 时,会暂存失败的请求, 刷新 token 成功后,重新发送这些暂存的请求。
:::
在 vite.config.ts,参考下面代码配置本地跨域代理即可:
const isDev = process.env.NODE_ENV === "development";
export default defineConfig({
server: {
port: 3333,
// https://vitejs.dev/config/server-options#server-proxy
proxy: {
"/api": {
target: "http://191.255.255.123:8888", // [!code ++]
changeOrigin: true,
rewrite: path => isDev ? path.replace(/^\/api/, "") : path,
},
},
},
});
包括不限于以下优点:
.json() 解析为 unknown 类型::: info Ky VS Fetch
:::
虽然原生的 Fetch 不支持获取文件下载进度百分比,但 Ky 提供了进度回调函数,解决了这个问题。
::: info onDownloadProgress 进度回调函数
import ky from "ky";
const response = await ky("https://example.com", {
onDownloadProgress: (progress, chunk) => {
// Example output:
// `0% - 0 of 1271 bytes`
// `100% - 1271 of 1271 bytes`
console.log(`${progress.percent * 100}% - ${progress.transferredBytes} of ${progress.totalBytes} bytes`);
}
});
:::
Axios 是基于 XmlHttpRequest 的。gzip 压缩后大小为 11.7KB。 Ky 是基于 fetch 的。gzip 压缩后大小为 3.3KB。 Ky 的包大小较小。