封装通用的请求函数(uniapp + vue3 + ts + pinia)
- 实现请求时统一携带 token 等请求头参数
- 对请求成功的数据进行解耦
- 对请求失败的数据进行处理
import { useMemberStore } from '@/stores/modules/member'
// 请求基地址
const baseURL = '请求基地址'
// 拦截器
const httpInterceptor = {
invoke(options: UniApp.RequestOptions) {
// 拼接请求地址 => 这里判断是为了防止请求时写了全地址
// 如果 options.url 不是以 http 开头 则进行拼接
if (!options.url.startsWith('http')) {
options.url = baseURL + options.url
}
// 请求超时
options.timeout = 10000
// 携带请求头
options.header = {
...options.header,
'source-client': 'miniapp',
}
// 携带token
const memberStore = useMemberStore()
const token = memberStore.profile?.token
if (token) {
options.header.Authorization = token
}
},
}
// request 和 uploadFile 都需要进行拦截处理
uni.addInterceptor('request', httpInterceptor)
uni.addInterceptor('uploadFile', httpInterceptor)
// 请求函数
// 返回数据类型
interface Data<T> {
code: string
msg: string
result: T
}
// 封装请求函数
export const http = <T>(options: UniApp.RequestOptions) => {
return new Promise<Data<T>>((resolve, reject) => {
uni.request({
...options,
// 响应成功
success(res) {
// 成功的状态码 => 具体状态码根据实际情况进行修改
if (res.statusCode >= 200 && res.statusCode < 300) {
resolve(res.data as Data<T>)
} else if (res.statusCode === 401) {
// 401 错误
const memberStore = useMemberStore()
memberStore.clearProfile()
uni.navigateTo({ url: '/pages/login/login' })
reject(res)
} else {
// 其他错误
uni.showToast({
icon: 'none',
title: (res.data as Data<T>).msg || '请求错误',
})
}
},
// 响应失败
fail(err) {
uni.showToast({
icon: 'none',
title: '网络错误 请稍后重试',
})
reject(err)
},
})
})
}