Axios在鸿蒙应用开发中的使用
目录
- 一、简介
- 二、安装与配置
- 三、axios用法
- 1.axios泛型参数
- (1).第三个泛型参数-约束data请求参数的类型
- (2).第二个泛型参数-决定后台返回数据的类型
- 2.axios拦截器
- 3.请求工具封装
- 统一处理业务状态码错误
- 统一处理401或404错误
一、简介
Axios 是一个基于 Promise 的网络请求库,可以运行在 Node.js 和浏览器中。在鸿蒙生态中,它是基于 http 模块封装的优秀请求库。
选择 Axios 的原因:
- 多平台实现:可用鸿蒙、前端、NodeJS 后端
- 质量稳定:ohos 官方推荐的第三方仓库
- 支持拦截器:请求拦截器,响应拦截器(通用业务处理)
Axios 的核心能力包括:
- HTTP 请求
- Promise API
- request 和 response 拦截器
- 转换 request 和 response 的 data 数据
- 自动转换 JSON data 数据
接口与属性列表
接口列表
接口 | 参数 | 功能 |
---|---|---|
axios(config) | config:请求配置 | 发送请求 |
axios.create(config) | config:请求配置 | 创建实例 |
axios.request(config) | config:请求配置 | 发送请求 |
axios.get(url[, config]) | url:请求地址config:请求配置 | 发送get请求 |
axios.delete(url[, config]) | url:请求地址config:请求配置 | 发送delete请求 |
axios.post(url[, data[, config]]) | url:请求地址 data:发送请求体数据 config:请求配置 | 发送post请求 |
axios.put(url[, data[, config]]) | url:请求地址 data:发送请求体数据 config:请求配置 | 发送put请求 |
属性列表
属性 | 描述 |
---|---|
axios.defaults[‘xxx’] | 默认设置 。值为请求配置 config 中的配置项 例如 axios.defaults.headers 获取头部信息 |
axios.interceptors | 拦截器 |
二、安装与配置
下载安装
需要权限
在src/main/module.json5中添加网络权限
三、axios用法
1.axios泛型参数
(1).第三个泛型参数-约束data请求参数的类型
/** 账号密码登录模型*/
export interface ApifoxModel1 {/*** 用户密码*/passwd?: string;/*** 用户手机号*/phone?: string;
}
Button('泛型参数-约束post请求参数').onClick(async () => {// 第三个泛型参数:约束请求体(data)参数的类型 - 重点await axios.post<null, null, PostUserLoginPasswdData>('https://guardianapi.itheima.net/user/login/passwd',{phone: '120666666666',passwd: '888itcast.CN764%...'})promptAction.showToast({message: '登录请求发送成功'})
})
(2).第二个泛型参数-决定后台返回数据的类型
/*** 数据响应模型«登录VO»*/
export interface ServiceResponse<R> {/*** 请求码,200为成功,300及300以上为请求失败*/code: number;/*** 响应信息*/msg?: string;/*** 响应时间*/resTime?: Date;result?: R;tips?: string;
}
/*** 登录VO*/
export interface LoginResult {/*** 访问token,有效期1小时*/accessToken?: string;/*** 头像*/avatar?: string;/*** 昵称*/nickname?: string;/*** 续期token,有效期30天*/renewalToken?: string;
}
Button('泛型参数-约束post请求参数').onClick(async () => {// 第三个泛型参数:约束请求体(data)参数的类型 - 重点// res的类型由第二个参数来决定// 第一个泛型参数:会被覆盖掉const res = await axios.post<null, AxiosResponse<ServiceResponse<LoginResult>, null>, PostUserLoginPasswdData>('https://guardian-api.itheima.net/user/login/passwd',{"phone": "120666666672","passwd": "888itcast.CN764%..."})promptAction.showToast({message: '登录请求发送成功'})//AlertDialog.show({message: JSON.stringify(res, null, 2)})if (res.data.code === 200) {this.avatar = res.data.result?.avatar as string} else {}})
Image(this.avatar).width(200)
Divider().strokeWidth(1)
2.axios拦截器
在请求或响应被then或catch处理前拦截它们
Button('创建axios实例').onClick(async () => {// 0.创建axios实例const axiosInstance = axios.create({baseURL: 'https://guardian-api.itheima.net',timeout: 20 * 1000 //超时时间})// 注意复制过来拦截器的结构后,把axios替换成axiosInstance 实例// 1.axios请求拦截器axiosInstance.interceptors.request.use((config: InternalAxiosRequestConfig) => {config.headers.Authorization = 'token_xxxx'console.log('interceptors request', JSON.stringify(config));return config},(error: AxiosError) => {return Promise.reject(error)})//2.添加相应拦截器axiosInstance.interceptors.response.use(//对响应数据做点儿什么(response: AxiosResponse) => {return response},(error: AxiosError) => {//对响应错误做点儿什么return Promise.reject(error)});// -----const res = await axiosInstance.post<null, AxiosResponseData<LoginResult>, PostUserLoginPasswdData> ('/user/login/passwd', {phone: '120666666672',passwd: '888itcast.CN764%...'})if (res.data.code === 200) {this.avatar = res.data.result?.avatar as string} else {promptAction.showToast({message: res.data.msg})}})
3.请求工具封装
统一处理业务状态码错误
// http.ets
import axios, { AxiosResponse, InternalAxiosRequestConfig, AxiosError } from '@ohos/axios'
import { promptAction } from '@kit.ArkUI';/*** 后端响应基本类型*/
export interface ServiceResponse<T> {/** 请求码,200为成功,300及300以上为请求失败 */code: number;msg: string;resTime: Date;result: T;tips: string;
}// type 类型别名, 保存类型
// 三层对象嵌套:Axios 响应类型 > 后端响应基本类型 > 不同接口响应的类型
export type AxiosResponseData<Result = null> = AxiosResponse<ServiceResponse<Result>, null>export const axiosInstance = axios.create({baseURL: 'https://guardian-api.itheima.net',timeout: 1000*20
})// 添加请求拦截器
axiosInstance.interceptors.request.use((config:InternalAxiosRequestConfig) => {// 对请求数据做点什么return config;
}, (error:AxiosError) => {// 对请求错误做些什么return Promise.reject(error);
});// 添加响应拦截器
axiosInstance.interceptors.response.use((response:AxiosResponseData)=> {if (response.data.code == 200) {return response;} else {promptAction.showToast({message: response.data.msg})return Promise.reject() // 中断await后续代码的执行}// 对响应数据做点什么return response;
}, (error:AxiosError)=> {// 对响应错误做点什么return Promise.reject(error);
});
//Index.ets
Button('请求工具-发送登录请求').onClick(async () => {const res = await axiosInstance.post<null,AxiosResponseData<LoginResult>, PostUserLoginPasswdData>('/user/login/passwd',{phone: '111', passwd: '222'})//直接书写参数正确时的逻辑即可,错误由拦截器统一处理this.avatar = res.data.result?.avatar as stringAlertDialog.show({message: JSON.stringify(res, null, 2)})})
统一处理401或404错误
interface GetUserMeResponse {avatar?: string;nickname?: string;
}
Button('请求工具-发送获取我的用户信息').onClick( async () => {const res = await axiosInstance.get<null,AxiosResponseData<GetUserMeResponse>>('/user/me')this.avatar = res.data.result?.avatar as string
})
Button('请求工具-测试错误url路径').onClick(async () => {await axiosInstance.get('/user/meee')
})
// 添加响应拦截器
axiosInstance.interceptors.response.use((response:AxiosResponseData)=> {if (response.data.code == 200) {return response;} else {promptAction.showToast({message: response.data.msg})return Promise.reject() //中断await后续代码的执行}// 对响应数据做点什么return response;
}, (error:AxiosError)=> {// 401错误统一处理if(error.message.includes('401')) {promptAction.showToast({message: '登录信息无效,请重新登录'})} else if (error.message.includes('404')) {promptAction.showToast({message: '请求地址无效'})} else {promptAction.showToast({message: '未知网络错误'})}// 清空无效的用户信息// 对响应错误做点什么return Promise.reject(error);
});