【HarmonyOS Next】封装一个网络请求模块
环境准备
在开始之前,确保你已经安装了以下依赖:
@ohos/axios
:用于发起 HTTP 请求。@ohos.router
:用于页面跳转。@kit.ArkUI
:用于显示提示信息。@kit.ArkTS
:用于 JSON 操作。
安装方法:
bash
npm install @ohos/axios @ohos.router @kit.ArkUI @kit.ArkTS
封装步骤
1. 导入依赖
首先,我们需要导入所需的模块:
typescript
import axios, { InternalAxiosRequestConfig, AxiosResponse, AxiosError, AxiosRequestConfig, AxiosInstance } from '@ohos/axios';
import router from '@ohos.router';
import { promptAction } from '@kit.ArkUI';
import PreferencesUtils from './PreferencesUtils';
import { JSON } from '@kit.ArkTS';
2. 定义 API 响应接口
为了更好地处理 API 响应,我们定义一个泛型接口 ApiResponse
:
typescript
interface ApiResponse<T> {
data: T;
message?: string;
code?: string; // 统一为字符串类型
msg?: string;
}
3. 创建 axios 实例
创建一个 axios 实例,并设置基础 URL、超时时间和默认请求头:
typescript
const instance: AxiosInstance = axios.create({
baseURL: 'https://zhdj.changhong.com',
timeout: 10000, // 10秒超时
headers: { 'Content-Type': 'application/json' },
});
4. 设置请求拦截器
在请求发送前,我们可以对请求配置进行修改,例如添加 token 和其他公共请求头:
typescript
instance.interceptors.request.use(async (config: InternalAxiosRequestConfig) => {
console.log('instance.interceptors.request:', JSON.stringify(config));
// 从 PreferencesUtils 中异步获取 token
const token = await PreferencesUtils.get("token");
console.log('instance.interceptors.request:token:', token);
if (token) {
config.headers['Authorization'] = "Bearer " + token; // 设置 token
config.headers['System-id'] = "3";
}
return config;
}, (error: AxiosError) => {
// 请求错误处理
return Promise.reject(error);
});
5. 设置响应拦截器
在响应返回后,我们可以对响应数据进行处理,例如根据状态码显示提示信息或跳转到登录页面:
typescript
instance.interceptors.response.use((response: AxiosResponse) => {
console.log('cwx-response:', JSON.stringify(response));
// 根据项目的实际情况处理响应
if (response?.data?.code === '500') {
promptAction.showToast({
message: response.data.message, // 修正拼写错误
duration: 500,
alignment: Alignment.Center
});
return Promise.reject(response.data);
}
if (response?.data?.code === '200') {
return Promise.resolve(response.data);
}
return response.data;
}, (error: AxiosError) => {
console.log('AxiosError:', JSON.stringify(error.response));
const status = error.response?.status;
switch (status) {
case 401: // 无权限未登录
router.pushUrl({
url: 'pages/login'
});
break;
default:
promptAction.showToast({
message: '系统异常,请稍后再试!',
duration: 2000,
alignment: Alignment.Center
});
break;
}
return Promise.reject(error);
});
6. 封装请求方法
最后,我们将所有逻辑封装在一个泛型函数中,以便在应用中方便地调用:
typescript
// 暴露封装请求--每次调用这个方法时,不会重复添加拦截器
export default <T>(config: AxiosRequestConfig): Promise<ApiResponse<T>> => {
return instance(config);
};
使用示例
封装完成后,我们可以在应用中轻松使用这个网络请求模块。以下是一个简单的示例:
typescript
import request from './request';
const getUserInfo = async (): Promise<ApiResponse<User>> => {
const response = await request({
url: '/api/user/info',
method: 'GET',
});
return response;
};
const postData = async (data: PostData): Promise<ApiResponse<PostResponse>> => {
const response = await request({
url: '/api/data/post',
method: 'POST',
data: data,
});
return response;
};
// 调用示例
getUserInfo().then(userInfo => {
console.log('用户信息:', JSON.stringify(userInfo));
}).catch(error => {
console.error('获取用户信息失败:', error);
});
postData({ title: '测试标题', content: '测试内容' }).then(postResponse => {
console.log('数据提交成功:', JSON.stringify(postResponse));
}).catch(error => {
console.error('数据提交失败:', error);
});
总结
通过上述步骤,我们成功地在鸿蒙 Next 中封装了一个强大的网络请求模块。这个模块不仅简化了网络请求的代码,还通过请求和响应拦截器增强了请求的健壮性和用户体验。
附录:完整代码
typescript
import axios, { InternalAxiosRequestConfig, AxiosResponse, AxiosError, AxiosRequestConfig, AxiosInstance } from '@ohos/axios';
import router from '@ohos.router';
import { promptAction } from '@kit.ArkUI';
import PreferencesUtils from './PreferencesUtils';
import { JSON } from '@kit.ArkTS';
interface ApiResponse<T> {
data: T;
message?: string;
code?: string; // 统一为字符串类型
msg?: string;
}
// 创建 axios 实例
const instance: AxiosInstance = axios.create({
baseURL: 'https://zhdj.changhong.com',
timeout: 10000, // 10秒超时
headers: { 'Content-Type': 'application/json' },
});
// 设置请求拦截器
instance.interceptors.request.use(async (config: InternalAxiosRequestConfig) => {
console.log('instance.interceptors.request:', JSON.stringify(config));
// 从 PreferencesUtils 中异步获取 token
const token = await PreferencesUtils.get("token");
console.log('instance.interceptors.request:token:', token);
if (token) {
config.headers['Authorization'] = "Bearer " + token; // 设置 token
config.headers['System-id'] = "3";
}
return config;
}, (error: AxiosError) => {
// 请求错误处理
return Promise.reject(error);
});
// 设置响应拦截器
instance.interceptors.response.use((response: AxiosResponse) => {
console.log('cwx-response:', JSON.stringify(response));
// 根据项目的实际情况处理响应
if (response?.data?.code === '500') {
promptAction.showToast({
message: response.data.message, // 修正拼写错误
duration: 500,
alignment: Alignment.Center
});
return Promise.reject(response.data);
}
if (response?.data?.code === '200') {
return Promise.resolve(response.data);
}
return response.data;
}, (error: AxiosError) => {
console.log('AxiosError:', JSON.stringify(error.response));
const status = error.response?.status;
switch (status) {
case 401: // 无权限未登录
router.pushUrl({
url: 'pages/login'
});
break;
default:
promptAction.showToast({
message: '系统异常,请稍后再试!',
duration: 2000,
alignment: Alignment.Center
});
break;
}
return Promise.reject(error);
});
// 暴露封装请求--每次调用这个方法时,不会重复添加拦截器
export default <T>(config: AxiosRequestConfig): Promise<ApiResponse<T>> => {
return instance(config);
};