作者:前端小王hs
阿里云社区博客专家/清华大学出版社签约作者✍/CSDN百万访问博主/B站千粉前端up主
封装请求配置项
- 封装拦截器
- 封装uni.request
封装拦截器
uniapp
的封装逻辑不同于Vue3
项目中直接使用axios.create()
方法创建实例(在create
方法中写入请求的地址、请求头、超时等内容),代码如下:
const instance = axios.create({// 后端url地址baseURL: import.meta.env.VITE_API_BASEURL,timeout: 6000, //设置超时headers: {'Content-Type': 'application/x-www-form-urlencoded'}
});
PS:上述代码来自博主在B站的Vue3全家桶+MySQL+Express全栈实战项目源码
在uniapp
中,需要使用到一个官方的API
即uni.addInterceptor(STRING, OBJECT)
,这是一个用于拦截作用的API
,在规范开发的过程中,会在请求之前为请求的内容拼接url
、超时和请求头等信息,这一点在官方文档API
的基础拦截器一文中详细的示例,代码如下:
uni.addInterceptor('request', {invoke(args) {// request 触发前拼接 url args.url = 'https://www.example.com/'+args.url},success(args) {// 请求成功后,修改code值为1args.data.code = 1}, fail(err) {console.log('interceptor-fail',err)}, complete(res) {console.log('interceptor-complete',res)}
})
所以可以封装一个拦截器的配置项,为所有的uni.request
添加请求前置信息,代码如下:
const baseURL = import.meta.env.VITE_API_BASEURL
// 添加拦截器
const httpInterceptor = {// 拦截前触发invoke(options: UniApp.RequestOptions) {// 假设开头为非http的请求url地址if (!options.url.startsWith('http')) {options.url = baseURL + options.url}// 请求超时options.timeout = 6000options.header = {...options.header,// 自定义标识符,用于后端区分app、后台或其他渠道请求'source-client': 'app',}// 添加 token 请求头标识const token = uni.getStorage('token')if (token) {options.header.Authorization = token}},
}uni.addInterceptor('request', httpInterceptor)
这是一段万能的uniapp
封装拦截器代码,读者可收藏此文章粘贴即用,下同
封装uni.request
这里的封装,参考了axios
返回promise
对象的实现逻辑,在接口中return
一个promise
对象,便于在实际环境中更好的获取数据以及进一步处理数据,代码如下:
type Data<T> = {// 后端返回的通用响应结构statusCode: stringmsg: stringresult: T
}
// UniApp.RequestOptions为配置网络请求的选项
// 这里使用了泛型,便于自定义响应结构
export const http = <T>(options: UniApp.RequestOptions) => { return new Promise<Data<T>>((resolve, reject) => { uni.request({ // 拦截器配置内容...options,success(res) {// 成功响应handleResponse(res, resolve, reject);}, fail(err) { handleError(err, reject);}, }); };
}; // resolve和reject不返回任何值,但通知promise更改状态
const handleResponse = <T>(res: any, resolve: (value: Data<T>) => void, reject: (reason?: any) => void) => {// 分离了验证状态码逻辑if (isSuccessStatusCode(res.statusCode)) { resolve(res.data as Data<T>);// 登录失败} else if (res.statusCode === 401) { // 假设 clearUserInfo 是清除用户信息的函数 clearUserInfo();// 跳转至登录页面uni.navigateTo({ url: '/pages/login/index' });reject(res);} else {// 分离了报错状态码逻辑showErrorToast(res.data as Data<T>); reject(res);}
}; const handleError = (err: any, reject: (reason?: any) => void) => {uni.showToast({icon: 'none', title: '网络可能开小差了~', });reject(err);
};const isSuccessStatusCode = (statusCode: number) => {return statusCode >= 200 && statusCode < 300;
};const showErrorToast = <T>(data: Data<T>) => {uni.showToast({icon: 'none',title: data.msg || '请求错误',});
};
关于RequestOptions
更多的信息,可以对其ctrl+点击
查看内置的接口信息,如下图所示: