废话不多说直接上代码
import { refreshToken } from '@/api/login.js' //接口请求
// 是否正在刷新的标记
let isRefreshing = false
// 重试队列,每一项将是一个待执行的函数形式
let requests = []
// 此vm参数为页面的实例,可以通过它引用vuex中的变量
module.exports = (vm) => {
// 初始化请求配置
uni.$u.http.setConfig((config) => {
/* config 为默认全局配置*/
config.baseURL = 'https://aaa.com'; /* 根域名 */
return config
})
// 请求拦截
uni.$u.http.interceptors.request.use((config) => { // 可使用async await 做异步操作
// 添加请求头
config.header['tenant-id'] = '1'
// 初始化请求拦截器时,会执行此方法,此时data为undefined,赋予默认{}
config.data = config.data || {}
// 根据custom参数中配置的是否需要token,添加对应的请求头
const token = uni.getStorageSync('token');
if (token.accessToken) {
// 可以在此通过vm引用vuex中的变量,具体值在vm.$store.state中
config.header.Authorization = 'Bearer ' + token.accessToken
}
return config
}, config => { // 可使用async await 做异步操作
return Promise.reject(config)
})
// 响应拦截
uni.$u.http.interceptors.response.use(async (response) => {
/* 对响应成功做点什么 可使用async await 做异步操作*/
const data = response.data // 因为我这里后端做了深层嵌套返回数据,所以需要先拿到底层
// 无感刷新token
if (data.code === 401) {
//token无效或已过期
if (!isRefreshing) {
// 是否已经执行刷新
isRefreshing = true
let token = uni.getStorageSync('token') // 获取到过期的token,我这里是个对象
// 我是采用了封装请求的方式,这个无所谓,只要请求就好了
let res = await refreshToken({
refreshToken: token.refreshToken // 刷新token的令牌存在token的对象里面,需要传给后端
})
// 请求成功,开启刷新标识
isRefreshing = false
// 请求成功把新的token存到本地
uni.setStorageSync('token', res)
// 已经刷新了token,将所有队列中的请求进行重试
requests.forEach((item) => item(res.accessToken))
requests = []
}
// 每个接口请求都要存入队列,等刷新完以后都需要执行
return new Promise((resolve) => {
// 将resolve放进队列,用一个函数形式来保存,等token刷新后直接执行
requests.push((token) => {
//这一步一定要有,刷新token,因为存入的信息是旧的token
response.config.header = {
Authorization: "Bearer " + token,
}
resolve(uni.$u.http.request(response.config)) //执行请求
})
})
}
return data.data === undefined ? {} : data.data
}, (response) => {
// 对响应错误做点什么 (statusCode !== 200)
return Promise.reject(response)
})
}