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等通用头部。
constinstance=axios.create({baseURL:ApiConfig.getBaseUrl(),// 环境切换:dev/prodtimeout:30000,headers:{'Content-Type':'application/json'}});2. 拦截器机制
拦截器是 Axios 最强大的扩展点。MoneyTrack 使用多个拦截器实现关注点分离,多个请求拦截器按注册顺序先注册先执行,多个响应拦截器按注册顺序先注册后执行。
请求拦截器链路:请求拦截器①(Token注入)→ 请求拦截器②(日志打点)→ 发送网络请求 → 响应拦截器①(状态码解析)→ 响应拦截器②(错误分类处理)
请求拦截器:注入 Token + 日志打点
// 请求拦截器① — Token 注入instance.interceptors.request.use((config)=>{consttoken=AppStorage.get<string>('token');if(token){config.headers.Authorization=`Bearer${token}`;}returnconfig;},(error)=>Promise.reject(error));// 请求拦截器② — 日志打点instance.interceptors.request.use((config)=>{console.info(`[Network]${config.method?.toUpperCase()}${config.url}`);returnconfig;},(error)=>Promise.reject(error));响应拦截器:解析 data + 错误分类处理
// 响应拦截器① — 状态码校验instance.interceptors.response.use((response:AxiosResponse)=>{if(response.status===200){returnPromise.resolve(response.data);}Logger.error('[Network]',`请求失败:${response.config.url}`,JSON.stringify(response.status));returnPromise.reject(response);},(error:BusinessError)=>{// 错误分类处理if(error.code==='ECONNABORTED'){// 超时错误returnhandleTimeoutRetry(error);}elseif(!error.response){// 断网错误ReminderUtil.showToast('网络异常,请检查网络连接');}Logger.error('[Network]',`请求失败:`,JSON.stringify(error));returnPromise.reject(error);});3. 超时重试机制
对于超时或可恢复的网络错误,采用"最大重试次数 + 固定延迟"的策略自动重试:
asyncfunctionhandleTimeoutRetry(error:BusinessError,retryCount=3):Promise<any>{constconfig=error.config;if(!config||!config._retryCount){config._retryCount=0;}if(config._retryCount<retryCount){config._retryCount++;console.info(`[Network] 第${config._retryCount}次重试:${config.url}`);returnnewPromise((resolve)=>setTimeout(resolve,1000)).then(()=>instance.request(config));}returnPromise.reject(error);}4. 环境切换
通过ApiConfig模块根据构建标识自动切换 baseURL,实现一套代码多环境部署:
exportclassApiConfig{staticgetBaseUrl():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,在页面离开时取消未完成的请求,避免内存泄漏。
推荐参考文档
- @ohos/axios API 参考
- Axios 官方文档