基于Axios的ArkTS网络请求封装指南
在现代前端开发中,网络请求是必不可少的部分。Axios作为最流行的HTTP客户端之一,提供了简洁的API和强大的功能。本文将介绍如何在ArkTS中基于Axios进行网络请求的封装,以提高代码的可维护性和复用性。
1. 安装Axios
首先,确保你的项目已经安装了Axios:
bash
复制
npm install axios
# 或者
yarn add axios
2. 基础封装实现
2.1 创建基础请求类
typescript
复制
// utils/http.ts
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
class HttpRequest {
private instance: AxiosInstance;
constructor(config: AxiosRequestConfig) {
this.instance = axios.create(config);
// 请求拦截器
this.instance.interceptors.request.use(
(config) => {
// 可以在这里添加token等公共请求头
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
// 响应拦截器
this.instance.interceptors.response.use(
(response: AxiosResponse) => {
// 对响应数据做统一处理
const { data } = response;
if (data.code === 200) {
return data;
} else {
// 处理业务错误
return Promise.reject(new Error(data.message || '请求失败'));
}
},
(error) => {
// 处理HTTP错误
if (error.response) {
switch (error.response.status) {
case 401:
// 跳转到登录页
break;
case 403:
// 提示权限不足
break;
case 404:
// 提示资源不存在
break;
case 500:
// 提示服务器错误
break;
}
}
return Promise.reject(error);
}
);
}
public request<T = any>(config: AxiosRequestConfig): Promise<T> {
return this.instance.request(config);
}
public get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
return this.instance.get(url, config);
}
public post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
return this.instance.post(url, data, config);
}
public put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
return this.instance.put(url, data, config);
}
public delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
return this.instance.delete(url, config);
}
}
// 创建默认实例
const http = new HttpRequest({
baseURL: process.env.API_BASE_URL || '/api',
timeout: 10000,
headers: {
'Content-Type': 'application/json',
},
});
export default http;
2.2 使用封装后的请求
typescript
复制
// api/user.ts
import http from '../utils/http';
export const getUserInfo = (userId: string) => {
return http.get(`/user/${userId}`);
};
export const updateUserInfo = (userId: string, data: any) => {
return http.put(`/user/${userId}`, data);
};
export const login = (username: string, password: string) => {
return http.post('/auth/login', { username, password });
};
3. 高级功能扩展
3.1 添加取消请求功能
typescript
复制
// 在HttpRequest类中添加
private cancelTokenSource = axios.CancelToken.source();
public cancelRequest(message?: string) {
this.cancelTokenSource.cancel(message);
this.cancelTokenSource = axios.CancelToken.source(); // 重置
}
// 修改request方法
public request<T = any>(config: AxiosRequestConfig): Promise<T> {
const newConfig = {
...config,
cancelToken: this.cancelTokenSource.token
};
return this.instance.request(newConfig);
}
3.2 添加请求重试机制
typescript
复制
// 在响应拦截器中添加重试逻辑
this.instance.interceptors.response.use(
(response) => response,
async (error) => {
const config = error.config;
// 如果配置了重试次数且当前重试次数小于配置值
if (config.retry && config.retryCount < config.retry) {
config.retryCount = config.retryCount || 0;
config.retryCount++;
// 等待一段时间后重试
await new Promise(resolve => setTimeout(resolve, config.retryDelay || 1000));
return this.instance(config);
}
return Promise.reject(error);
}
);
3.3 添加缓存功能
typescript
复制
// 在HttpRequest类中添加缓存功能
private cache = new Map<string, any>();
public getWithCache<T = any>(url: string, config?: AxiosRequestConfig & { cacheKey?: string, cacheTime?: number }): Promise<T> {
const cacheKey = config?.cacheKey || url;
const cacheTime = config?.cacheTime || 60000; // 默认缓存1分钟
if (this.cache.has(cacheKey)) {
return Promise.resolve(this.cache.get(cacheKey));
}
return this.get(url, config).then(response => {
this.cache.set(cacheKey, response);
setTimeout(() => this.cache.delete(cacheKey), cacheTime);
return response;
});
}
4. 最佳实践建议
- 统一错误处理:在拦截器中统一处理错误,避免在每个请求中重复处理
- 类型安全:为API响应定义明确的类型,提高代码的可维护性
- 环境配置:根据不同的环境(开发、测试、生产)配置不同的baseURL
- 请求节流:对于频繁触发的请求(如搜索建议),添加防抖或节流机制
- Mock数据:开发阶段可以使用Mock数据,便于前后端并行开发
5. 完整示例
typescript
复制
// utils/http.ts
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
interface CustomConfig extends AxiosRequestConfig {
retry?: number;
retryCount?: number;
retryDelay?: number;
cacheKey?: string;
cacheTime?: number;
}
class HttpRequest {
private instance: AxiosInstance;
private cancelTokenSource = axios.CancelToken.source();
private cache = new Map<string, any>();
constructor(config: AxiosRequestConfig) {
this.instance = axios.create(config);
this.setupInterceptors();
}
private setupInterceptors() {
// 请求拦截器
this.instance.interceptors.request.use(
(config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error)
);
// 响应拦截器
this.instance.interceptors.response.use(
(response: AxiosResponse) => {
const { data } = response;
if (data.code === 200) {
return data;
}
return Promise.reject(new Error(data.message || '请求失败'));
},
async (error) => {
const config = error.config as CustomConfig;
// 请求重试
if (config.retry && (config.retryCount || 0) < config.retry) {
config.retryCount = (config.retryCount || 0) + 1;
await new Promise(resolve => setTimeout(resolve, config.retryDelay || 1000));
return this.instance(config);
}
// 错误处理
if (error.response) {
// 处理HTTP错误状态码
// ...
}
return Promise.reject(error);
}
);
}
public cancelRequest(message?: string) {
this.cancelTokenSource.cancel(message);
this.cancelTokenSource = axios.CancelToken.source();
}
public request<T = any>(config: CustomConfig): Promise<T> {
const newConfig = {
...config,
cancelToken: this.cancelTokenSource.token
};
return this.instance.request(newConfig);
}
public get<T = any>(url: string, config?: CustomConfig): Promise<T> {
return this.request({ ...config, method: 'GET', url });
}
public getWithCache<T = any>(url: string, config?: CustomConfig): Promise<T> {
const cacheKey = config?.cacheKey || url;
const cacheTime = config?.cacheTime || 60000;
if (this.cache.has(cacheKey)) {
return Promise.resolve(this.cache.get(cacheKey));
}
return this.get(url, config).then(response => {
this.cache.set(cacheKey, response);
setTimeout(() => this.cache.delete(cacheKey), cacheTime);
return response;
});
}
public post<T = any>(url: string, data?: any, config?: CustomConfig): Promise<T> {
return this.request({ ...config, method: 'POST', url, data });
}
public put<T = any>(url: string, data?: any, config?: CustomConfig): Promise<T> {
return this.request({ ...config, method: 'PUT', url, data });
}
public delete<T = any>(url: string, config?: CustomConfig): Promise<T> {
return this.request({ ...config, method: 'DELETE', url });
}
}
const http = new HttpRequest({
baseURL: process.env.API_BASE_URL || '/api',
timeout: 10000,
headers: {
'Content-Type': 'application/json',
},
});
export default http;
结语
通过以上封装,我们实现了Axios在ArkTS中的高级封装,包括基础请求、拦截器、取消请求、请求重试和缓存等功能。这种封装方式可以提高代码的复用性,统一错误处理,并使网络请求更加健壮和易于维护。根据项目实际需求,你可以进一步扩展或调整这些功能。