Skip to content

Commit dbeaaa7

Browse files
committed
feat(axios): 更新 Axios 文档和注释,修正初始化方法说明
1 parent 37ceeeb commit dbeaaa7

3 files changed

Lines changed: 117 additions & 73 deletions

File tree

.changeset/early-suits-act.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@ethan-utils/axios": patch
3+
---
4+
5+
更新文档和注释

packages/axios/README.md

Lines changed: 110 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,114 +1,153 @@
1-
# Axios 封装
1+
# @ethan-utils/axios
22

3-
该包对 `axios` 进行了封装,提供了统一的 API 请求客户端
3+
高可用 axios 请求库,支持全局配置、请求拦截、响应拦截、自动重试、Token 注入、401 回调等功能,适用于前后端分离项目的 API 请求统一管理
44

55
## 特性
66

7-
- 单例模式:通过 `initApiClient` 初始化,全局共享一个 `axios` 实例。
8-
- 统一响应格式:默认请求方法返回 `BaseResponse<T>` 格式的数据。
9-
- 统一错误处理:自动捕获请求错误并返回标准化的错误响应。
10-
- TypeScript 支持:提供完整的类型定义。
11-
- 提供不包装响应体的方法:为特殊场景,提供了 `...WithoutBaseResponse` 系列方法。
7+
- **单例/多实例模式**:支持全局单例和多实例灵活切换。
8+
- **标准响应与原始响应**:所有请求方法分为标准响应(`BaseResponse`)和原始响应(`raw`)两类。
9+
- **自动重试**:网络错误和 5xx 状态自动重试。
10+
- **Token 注入**:支持动态获取 Token 并自动注入请求头。
11+
- **401 回调**:支持未授权自动回调处理。
12+
- **TypeScript 完全类型支持**
1213

1314
## 安装
1415

15-
由于是在 monorepo 环境中,您可以直接在其他包的 `package.json` 中添加依赖
16+
建议使用 pnpm 进行依赖管理
1617

17-
```json
18-
"dependencies": {
19-
"@ethan-utils/axios": "workspace:*"
20-
}
18+
```sh
19+
pnpm add @ethan-utils/axios axios axios-retry qs
2120
```
2221

23-
然后运行 `pnpm install`
22+
> 依赖:axios、axios-retry、qs
2423
25-
## 使用方法
24+
## 快速上手
2625

27-
### 1. 初始化
26+
### 1. 初始化全局请求客户端
2827

29-
在应用入口处(例如 `main.ts``app.ts`调用 `initApiClient` 来初始化请求客户端
28+
在应用入口(如 `main.ts``app.ts`)调用 `createRequest` 并设置为全局单例(默认即可),否则后续调用 `request` 会抛出错误
3029

3130
```typescript
32-
// src/main.ts
33-
import { initApiClient } from "@ethan-utils/axios";
31+
import { createRequest, request } from "@ethan-utils/axios";
3432

35-
initApiClient({
33+
createRequest({
3634
baseURL: "https://api.example.com",
3735
timeout: 10000,
38-
// 其他 axios 配置
36+
getToken: () => localStorage.getItem("token"), // 可选,自动注入 Authorization
37+
onUnauthorized: () => {
38+
// 可选,401 未授权时的处理
39+
window.location.href = "/login";
40+
},
3941
});
42+
43+
// 之后可直接使用 request 进行请求
4044
```
4145

4246
### 2. 发起请求
4347

44-
在需要发起 API 请求的地方,导入 `request` 对象。
45-
4648
```typescript
4749
import { request } from "@ethan-utils/axios";
4850

49-
interface User {
50-
id: number;
51-
name: string;
51+
// 标准响应(BaseResponse)
52+
const res = await request.get<User>("/users/1");
53+
if (res.code === 200) {
54+
console.log(res.data);
55+
} else {
56+
console.error(res.msg);
5257
}
5358

54-
// GET 请求
55-
async function getUser(id: number) {
56-
const res = await request.get<User>(`/users/${id}`);
57-
if (res.code === 200) {
58-
console.log(res.data); // { id: 1, name: 'John Doe' }
59-
} else {
60-
console.error(res.msg);
61-
}
62-
}
63-
64-
// POST 请求
65-
async function createUser(name: string) {
66-
const res = await request.post<{ success: boolean }>("/users", { name });
67-
if (res.code === 201) {
68-
console.log("User created");
69-
} else {
70-
console.error(res.msg);
71-
}
59+
// 原始响应(遇到错误直接抛出异常)
60+
try {
61+
const user = await request.raw.get<User>("/users/1");
62+
console.log(user);
63+
} catch (e) {
64+
// 需自行处理异常
7265
}
7366
```
7467

75-
### 3. 使用不带 BaseResponse 的方法
68+
### 3. 多实例用法
7669

77-
如果您的 API 端点没有遵循 `BaseResponse` 结构,可以使用 `WithoutBaseResponse` 系列方法。这些方法在成功时直接返回后端返回的 `data`,在失败时会直接抛出错误,需要您自行使用 `try...catch` 处理。
70+
如需隔离不同 API 客户端,可用 `createRequest` 创建多实例:
7871

7972
```typescript
80-
import { request } from "@ethan-utils/axios";
73+
import { createRequest } from "@ethan-utils/axios";
74+
75+
const api1 = createRequest({ baseURL: "https://api1.com" }, false); // 新实例
76+
const api2 = createRequest({ baseURL: "https://api2.com" }, false);
77+
78+
const res1 = await api1.get<any>("/foo");
79+
const res2 = await api2.get<any>("/bar");
80+
```
81+
82+
## API 说明
83+
84+
### 初始化
85+
86+
- `createRequest(options: CreateApiOptions, isSingleton = true)`:创建请求客户端,`isSingleton` 为 true 时返回全局单例,否则每次返回新实例。**如需初始化全局 request,直接调用一次即可。**
87+
- `request`:全局请求客户端代理,需先用 `createRequest` 初始化。
8188

82-
// 假设 /profile 直接返回用户对象
83-
interface Profile {
84-
username: string;
85-
email: string;
89+
### 请求方法
90+
91+
所有方法均支持标准响应(BaseResponse)和原始响应(raw):
92+
93+
- `get<T>(url, config?)`
94+
- `post<T>(url, data?, config?)`
95+
- `put<T>(url, data?, config?)`
96+
- `delete<T>(url, config?)`
97+
- `patch<T>(url, data?, config?)`
98+
99+
原始响应方法通过 `raw` 命名空间调用:
100+
101+
- `raw.get<T>(url, config?)`
102+
- `raw.post<T>(url, data?, config?)`
103+
- `raw.put<T>(url, data?, config?)`
104+
- `raw.delete<T>(url, config?)`
105+
- `raw.patch<T>(url, data?, config?)`
106+
107+
#### 返回值说明
108+
109+
- 标准响应:`Promise<BaseResponse<T>>`,失败时 code 非 200/201,data 为 null,msg 为错误信息。
110+
- 原始响应:`Promise<T>`,失败时直接抛出异常。
111+
112+
### 类型定义
113+
114+
```typescript
115+
/**
116+
* 标准化 API 响应结构
117+
*/
118+
export interface BaseResponse<T> {
119+
data: T; // 实际数据
120+
msg: string; // 提示信息
121+
code: number; // 业务状态码
86122
}
87123

88-
async function getProfile() {
89-
try {
90-
const profile = await request.getWithoutBaseResponse<Profile>("/profile");
91-
console.log(profile.username);
92-
} catch (error) {
93-
// 自行处理错误
94-
console.error("Failed to fetch profile:", error);
95-
}
124+
/**
125+
* 创建 API 实例的配置选项
126+
*/
127+
export interface CreateApiOptions {
128+
baseURL: string; // API 的基础 URL
129+
getToken?: () => string | null; // 获取认证令牌的函数
130+
onUnauthorized?: () => void; // 401 未授权时的回调
131+
timeout?: number; // 请求超时时间
96132
}
97133
```
98134

99-
## API
135+
## 注意事项
136+
137+
- **必须先初始化**:未初始化直接调用 `request` 会抛出 `API client has not been initialized. Please call createRequest() first.`
138+
- **Token 自动注入**:如需自动携带 token,传入 `getToken`
139+
- **401 处理**:如需自动跳转登录等,传入 `onUnauthorized`
140+
- **自动重试**:网络错误和 5xx 状态自动重试 3 次。
141+
- **request.r**`request` 还有一个简写别名 `r`,用法一致。
142+
143+
## 依赖
144+
145+
- axios
146+
- axios-retry
147+
- qs
100148

101-
`request` 对象包含以下方法:
149+
## 贡献与反馈
102150

103-
- `get<T>(url, config)`
104-
- `getWithoutBaseResponse<T>(url, config)`
105-
- `post<T>(url, data, config)`
106-
- `postWithoutBaseResponse<T>(url, data, config)`
107-
- `put<T>(url, data, config)`
108-
- `putWithoutBaseResponse<T>(url, data, config)`
109-
- `delete<T>(url, config)`
110-
- `deleteWithoutBaseResponse<T>(url, config)`
111-
- `patch<T>(url, data, config)`
112-
- `patchWithoutBaseResponse<T>(url, data, config)`
151+
如有问题或建议,欢迎提 issue 或 PR。
113152

114-
所有被 `BaseResponse` 包装的方法,当请求失败时,会返回一个 `BaseResponse` 对象,其中 `code` 通常不为 200 或 201 等成功状态码,`data``null``msg` 包含错误信息。
153+
- 仓库地址:https://github.com/ethanz-code/ethan-utils

packages/axios/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ export function createRequest(
195195
}
196196

197197
/**
198-
* 全局请求客户端,需先调用 initApiClient 初始化
198+
* 全局请求客户端,需先调用 createRequest 初始化
199199
* - request.get/post/put/delete/patch 返回 BaseResponse
200200
* - request.raw.get/post/put/delete/patch 返回原始 data,失败抛出异常
201201
*/
@@ -205,7 +205,7 @@ export const request = new Proxy(
205205
get(_, prop: string) {
206206
if (!apiClientInstance) {
207207
throw new Error(
208-
"API client has not been initialized. Please call initApiClient() first.",
208+
"API client has not been initialized. Please call createRequest() first.",
209209
);
210210
}
211211
return Reflect.get(apiClientInstance, prop);

0 commit comments

Comments
 (0)