asiox
添加网络权限
- 在
module.json5
中添加网络权限:
json
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}
]
}
}
安装
- 点击底部终端 输入命令
ts
ohpm install @ohos/axios
封装 axios
创建网络请求工具文件 ets/utils/request.ets
利用 axios 的 create 方法创建 axios 实例
配置我们全局公共的网络请求前缀 baseURL。
配置统一的超时时间 timeout
配置公共的统一 headers。
ts
import axios, {
InternalAxiosRequestConfig,
AxiosResponse,
AxiosError,
AxiosRequestConfig,
AxiosInstance,
} from "@ohos/axios";
// 创建实例
const instance: AxiosInstance = axios.create({
baseURL: "http://XXX.XX.XX.XX", //修改为自己项目的实际地址
timeout: 10000, //超时
headers: { "Content-Type": "application/json" },
// `transformRequest` 允许在向服务器发送前,修改请求数据 一般来说用不到,只要后端同志是正常的
// 它只能用于 'PUT', 'POST' 和 'PATCH' 这几个请求方法
// 数组中最后一个函数必须返回一个字符串, 一个Buffer实例,ArrayBuffer,FormData,或 Stream
// 你可以修改请求头。
// transformRequest: [(data: ESObject, headers: AxiosRequestHeaders) => {
// // 对发送的 data 进行任意转换处理
// // console.log('api1Result出零四',data)
// // return data
// }],
});
配置添加请求拦截器
ts
// 请求拦截器
instance.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
// 对请求数据做点什么
const token = "eyJhbw"; //自己根据自己项目实际情况获取
if (token) {
config.headers["token"] = token; //设置token
}
return config;
},
(error: AxiosError) => {
// 对请求错误做些什么
return Promise.reject(error);
}
);
配置添加响应拦截器
下面内容用到了@ohos.router
进行页面 跳转,用到了@kit.ArkUI'
的 promptAction.showToast
进行统一错误提示。 响应拦截非常重要,他是我们封装请求好用的关键,但是每个项目业务不同,其实响应拦截的配置都有不小的差异,但是整体思路是一致的,所以要根据自己的实际情况进行修改。
ts
// 添加响应拦截器
instance.interceptors.response.use(
(response: AxiosResponse) => {
// 对响应数据做点什么
// 因为 我们后台返回的 数据结构是统一的例如{code:2001,massage:'用户信息不能为空',data:{}}
// 所以下面配置根据系统返回来配置的,不同的系统配置不同
if (response.data.code == "2001") {
//这里是举例 要根据自己项目的实际情况进行处理
promptAction.showToast({
//用到了 @kit.ArkUI 的 promptAction进行系统弹窗提示
message: response.data.massage,
duration: 2000,
alignment: Alignment.Center,
});
return Promise.reject(response.data);
}
if (response.data.code == "4001") {
//这里是举例 要根据自己项目的实际情况进行处理
router.pushUrl({
//用到了 @ohos.router 进行页面跳转
url: "pages/LoginPage",
});
return Promise.reject(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({
//用到了 @ohos.router 进行页面跳转
url: "pages/LoginPage",
});
break;
default:
promptAction.showToast({
//用到了 @kit.ArkUI 的 promptAction进行系统弹窗提示
message: "系统异常,请稍后再试!",
duration: 2000,
alignment: Alignment.Center,
});
break;
}
return Promise.reject(error);
}
);
使用泛型 T 暴露我们请求的配置
在本例中我针对后端返回的数据如下:
ts
{
"code": 2001,
"message": "接口调用失败",
"data": { } //data的内容不是固定的可能是null,可能是对象,也可能是数组
}
因为我们接口返回结果不固定,所以我们利用一下 Ts 的 泛型暴露我们封装的请求。
完整的封装
ts
import axios, {
InternalAxiosRequestConfig,
AxiosResponse,
AxiosError,
AxiosRequestConfig,
AxiosInstance,
} from "@ohos/axios";
import router from "@ohos.router";
import { promptAction } from "@kit.ArkUI";
interface ApiResponse<T> {
//根据项目实际项目修改
data: T;
message?: string;
code?: number;
}
// 创建实例
const instance: AxiosInstance = axios.create({
baseURL: "http://XXX.XXX.XXX", //修改为自己项目的实际地址
timeout: 10000, //超时
headers: { "Content-Type": "application/json" },
});
//暴露封装请求--为什么没有把上面实例放入到下面中,避免每一个接口都去创建一次
//这里利用了泛型 T
export default <T>(config: AxiosRequestConfig): Promise<ApiResponse<T>> => {
// 请求拦截器
instance.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
// 对请求数据做点什么
const token = "eyJhbGciOiJ...."; //自己根据自己项目实际情况获取我大部分用的 @tencent/mmkv 插件
if (token) {
config.headers["authorization"] = token; //设置token
}
return config;
},
(error: AxiosError) => {
// 对请求错误做些什么
return Promise.reject(error);
}
);
// 添加响应拦截器
instance.interceptors.response.use(
(response: AxiosResponse) => {
// 对响应数据做点什么
// 因为 我们后台返回的 数据结构是统一的例如{code:2001,massage:'用户信息不能为空',data:{}}
// 所以下面配置根据系统返回来配置的,不同的系统配置不同
if (response.data.code == "2001") {
//这里是举例 要根据自己项目的实际情况进行处理
promptAction.showToast({
//用到了 @kit.ArkUI 的 promptAction进行系统弹窗提示
message: response.data.massage,
duration: 2000,
alignment: Alignment.Center,
});
return Promise.reject(response.data);
}
if (response.data.code == "4001") {
//这里是举例 要根据自己项目的实际情况进行处理
router.pushUrl({
//用到了 @ohos.router 进行页面跳转
url: "pages/LoginPage",
});
return Promise.reject(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({
//用到了 @ohos.router 进行页面跳转
url: "pages/LoginPage",
});
break;
default:
promptAction.showToast({
//用到了 @kit.ArkUI 的 promptAction进行系统弹窗提示
message: "系统异常,请稍后再试!",
duration: 2000,
alignment: Alignment.Center,
});
break;
}
return Promise.reject(error);
}
);
return instance(config);
};
代码示例示范统一管理接口配置(测试)
在 ets/api/index.ets
文件添加如下内容
ts
import request from "../utils/request";
interface LoginParams {
phone: string;
code: string | number;
}
//测试登录
export function TestLogin<T>(data: LoginParams) {
return request<T>({
url: "/test/login",
method: "post",
data,
});
}
//测试信息列表
export function parkList<T>(params: Record<string, string>) {
return request<T>({
url: "/test/parks",
method: "get",
params,
});
}
代码示例示范调用(测试)
ts
import {TestLogin } from "../api/index"
// 定义返回内容
interface ResponseLogin{
code:string,
result:string,
data:string
}
@Entry
@Component
struct Index {
async setTestLogin(){
const result = await TestLogin<ResponseLogin>({phone:'13111111',code:352})
if(result){
console.log('result',JSON.stringify(result))
console.log('code',JSON.stringify(result.code))
console.log('data',JSON.stringify(result.data))
}
}
build() {
RelativeContainer() {
Button('测试').onClick(()=>{
this.setTestLogin();
})
}
.height('100%')
.width('100%')
}
}
补充
就是不要用 .ets
后缀结尾。 可以 声明一个 type.d.ts
文件,然后再其他.ets
文件中引入是不会报错的。
也可以用下面的 类型去代替泛型 T。
ts
//嵌套未知类型
export interface PromiseObject {
[key: string]:
| string
| number
| object
| boolean
| undefined
| PromiseObject
| PromiseObject[]
| Array<string | number | boolean | PromiseObject | any>;
}
// any 类型
export type anyType = any;