网络请求
概述
网络请求模块封装了 HTTP 请求功能,提供统一的请求接口、拦截器机制和错误处理。
核心组件
| 组件 | 职责 |
|---|---|
| AxiosHttpClient | HTTP 客户端 |
| NetworkConfig | 网络配置 |
| RequestHelper | 请求辅助类 |
| HttpInterceptor | 拦截器接口 |
| NetworkResult | 网络结果封装 |
网络配置
NetworkConfig
typescript
interface NetworkConfig {
baseUrl: string; // API 基础地址
timeout: number; // 超时时间(毫秒)
responseParser: {
successCode: number; // 成功状态码
dataField: string; // 数据字段名
messageField: string; // 消息字段名
codeField: string; // 状态码字段名
};
headers: Record<string, string>; // 默认请求头
enableLog: boolean; // 是否启用日志
}配置示例
typescript
const config: NetworkConfig = {
baseUrl: "https://api.example.com/",
timeout: 10000,
responseParser: {
successCode: 1000,
dataField: 'data',
messageField: 'message',
codeField: 'code'
},
headers: {
'Content-Type': 'application/json'
},
enableLog: true
};HTTP 客户端
创建客户端
typescript
import { AxiosHttpClient, NetworkConfig } from "@core/network";
const client = new AxiosHttpClient(config);发起请求
typescript
// GET 请求
const response = await client.get<UserInfo>("/users/123");
// POST 请求
const response = await client.post<UserInfo>("/users", {
name: "张三",
email: "zhangsan@example.com"
});
// PUT 请求
const response = await client.put<UserInfo>("/users/123", {
name: "李四"
});
// DELETE 请求
const response = await client.delete("/users/123");拦截器
拦截器接口
typescript
interface HttpInterceptor {
onRequest(config: AxiosRequestConfig): Promise<AxiosRequestConfig>;
onResponse(response: AxiosResponse): Promise<AxiosResponse>;
onError(error: AxiosError): Promise<AxiosError>;
}创建拦截器
typescript
class AuthInterceptor implements HttpInterceptor {
async onRequest(config: AxiosRequestConfig): Promise<AxiosRequestConfig> {
// 添加认证信息
const token = await getToken();
if (token) {
config.headers = config.headers || {};
config.headers['Authorization'] = `Bearer ${token}`;
}
return config;
}
async onResponse(response: AxiosResponse): Promise<AxiosResponse> {
return response;
}
async onError(error: AxiosError): Promise<AxiosError> {
// 处理 401 错误
if (error.response?.status === 401) {
// 跳转到登录页
}
return error;
}
}注册拦截器
typescript
client.addInterceptor(new AuthInterceptor());
client.addInterceptor(new LogInterceptor());RequestHelper
简介
RequestHelper 提供了便捷的请求辅助方法,简化网络请求的使用。
使用示例
typescript
import { RequestHelper, NetworkResult } from "@core/network";
// 从 Promise 创建
RequestHelper.fromResult<UserInfo>(getUserInfo())
.toast(true) // 显示错误 Toast
.start(() => setLoading(true)) // 请求开始回调
.execute()
.then((data) => {
// 请求成功
console.log(data);
})
.catch(() => {
// 请求失败
});NetworkResult
结果封装
typescript
interface NetworkResult<T> {
success: boolean;
data?: T;
message?: string;
code?: number;
}创建结果
typescript
// 成功结果
const result: NetworkResult<UserInfo> = {
success: true,
data: userInfo,
code: 1000
};
// 失败结果
const result: NetworkResult<UserInfo> = {
success: false,
message: "用户不存在",
code: 4004
};使用示例
在 Service 中使用
typescript
import { getContainer, CoreServiceKeys } from "@core/di";
import { AxiosHttpClient, NetworkResult } from "@core/network";
export class UserService {
private httpClient: AxiosHttpClient;
constructor() {
const container = getContainer();
this.httpClient = container.resolve<AxiosHttpClient>(CoreServiceKeys.HttpClient);
}
async getUserInfo(userId: string): Promise<NetworkResult<UserInfo>> {
try {
const response = await this.httpClient.get<UserInfo>(`/users/${userId}`);
return {
success: true,
data: response.data
};
} catch (error) {
return {
success: false,
message: error.message
};
}
}
}在 ViewModel 中使用
typescript
import { BaseNetWorkViewModel } from "@core/base";
import { NetworkResult } from "@core/network";
@ObservedV2
export class UserProfileViewModel extends BaseNetWorkViewModel<UserInfo> {
private userService: UserService;
constructor() {
super();
this.userService = new UserService();
}
protected requestRepository(): Promise<NetworkResult<UserInfo>> {
return this.userService.getUserInfo("123");
}
}最佳实践
1. 统一错误处理
使用拦截器统一处理错误:
typescript
class ErrorInterceptor implements HttpInterceptor {
async onError(error: AxiosError): Promise<AxiosError> {
if (error.response) {
switch (error.response.status) {
case 401:
// 未授权,跳转登录
break;
case 403:
// 无权限
break;
case 404:
// 资源不存在
break;
case 500:
// 服务器错误
break;
}
}
return error;
}
}2. 请求取消
对于可能被取消的请求,使用 AbortController:
typescript
const controller = new AbortController();
client.get("/users", {
signal: controller.signal
});
// 取消请求
controller.abort();3. 请求重试
对于失败的请求,可以实现重试机制:
typescript
async function requestWithRetry<T>(
request: () => Promise<T>,
maxRetries: number = 3
): Promise<T> {
for (let i = 0; i < maxRetries; i++) {
try {
return await request();
} catch (error) {
if (i === maxRetries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
throw new Error("Max retries exceeded");
}注意事项
- 超时设置:合理设置超时时间,避免请求hang住
- 错误处理:始终处理网络错误
- 取消请求:在组件销毁时取消未完成的请求
- 安全性:不要在请求中包含敏感信息