037-axios网络请求封装
·
037 — @ohos/axios 网络请求封装:构建可复用的 HTTP 客户端
简介
在鸿蒙应用开发中,网络请求是连接客户端与服务端的核心桥梁。MoneyTrack 项目基于 @ohos/axios 库,通过单例模式封装了一个高度可复用的 HTTP 客户端,统一管理 baseURL、超时配置、请求/响应拦截器等关键能力。这套封装不仅减少了重复代码,更通过拦截器机制实现了全局错误处理、Token 注入、超时重试和日志打点,为上层 33+ 个 API 端点提供了稳定、一致的网络通信基础。
核心知识点
1. Axios 实例创建与全局配置
通过 axios.create() 创建自定义实例,集中管理全局配置,避免每个请求单独拼写:
- baseURL:统一设置服务端地址,支持通过环境变量切换 dev/prod 环境。
- 超时设置(30000ms):30 秒超时阈值,平衡用户体验与网络等待。配合超时重试机制,进一步提升弱网下的请求成功率。
- 请求头默认值:统一设置
Content-Type: application/json、Accept等通用头部。
const instance = axios.create({
baseURL: ApiConfig.getBaseUrl(), // 环境切换:dev/prod
timeout: 30000,
headers: { 'Content-Type': 'application/json' }
});
2. 拦截器机制
拦截器是 Axios 最强大的扩展点。MoneyTrack 使用多个拦截器实现关注点分离,多个请求拦截器按注册顺序先注册先执行,多个响应拦截器按注册顺序先注册后执行。
请求拦截器链路:请求拦截器①(Token注入)→ 请求拦截器②(日志打点)→ 发送网络请求 → 响应拦截器①(状态码解析)→ 响应拦截器②(错误分类处理)
请求拦截器:注入 Token + 日志打点
// 请求拦截器① — Token 注入
instance.interceptors.request.use(
(config) => {
const token = AppStorage.get<string>('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error)
);
// 请求拦截器② — 日志打点
instance.interceptors.request.use(
(config) => {
console.info(`[Network] ${config.method?.toUpperCase()} ${config.url}`);
return config;
},
(error) => Promise.reject(error)
);
响应拦截器:解析 data + 错误分类处理
// 响应拦截器① — 状态码校验
instance.interceptors.response.use(
(response: AxiosResponse) => {
if (response.status === 200) {
return Promise.resolve(response.data);
}
Logger.error('[Network]', `请求失败:${response.config.url}`, JSON.stringify(response.status));
return Promise.reject(response);
},
(error: BusinessError) => {
// 错误分类处理
if (error.code === 'ECONNABORTED') {
// 超时错误
return handleTimeoutRetry(error);
} else if (!error.response) {
// 断网错误
ReminderUtil.showToast('网络异常,请检查网络连接');
}
Logger.error('[Network]', `请求失败:`, JSON.stringify(error));
return Promise.reject(error);
}
);
3. 超时重试机制
对于超时或可恢复的网络错误,采用"最大重试次数 + 固定延迟"的策略自动重试:
async function handleTimeoutRetry(error: BusinessError, retryCount = 3): Promise<any> {
const config = error.config;
if (!config || !config._retryCount) {
config._retryCount = 0;
}
if (config._retryCount < retryCount) {
config._retryCount++;
console.info(`[Network] 第${config._retryCount}次重试:${config.url}`);
return new Promise((resolve) => setTimeout(resolve, 1000))
.then(() => instance.request(config));
}
return Promise.reject(error);
}
4. 环境切换
通过 ApiConfig 模块根据构建标识自动切换 baseURL,实现一套代码多环境部署:
export class ApiConfig {
static getBaseUrl(): string {
if (process.env.NODE_ENV === 'production') {
return 'https://api.moneytrack.com';
}
return 'https://dev-api.moneytrack.com';
}
}
请求拦截→发送→响应拦截完整链路
最佳实践
- Token 过期自动刷新:在响应拦截器中捕获 401 状态码,尝试调用刷新 Token 接口,成功后重放原始请求队列。
- 断网兜底:在网络不可用时,将请求暂存到离线队列,配合网络状态监听(见 041 篇)在网络恢复后自动重发。
- 拦截器顺序:多个请求拦截器按注册顺序依次执行;多个响应拦截器按注册顺序反向执行。需要先注入 Token 再打日志,因此 Token 拦截器先注册。
- 请求取消:使用
axios.CancelToken或AbortController,在页面离开时取消未完成的请求,避免内存泄漏。
推荐参考文档
更多推荐



所有评论(0)