场景:页面同时调用多个接口时token过期,需要刷新token并重新调用这些失败的接口并返回数据到页面。
难点:刷新token后重新调用接口数据并没有返回到页面。
// 标识 token 刷新状态
const isTokenRefreshing = false
// 存储因 token 刷新而挂起的请求
const failedRequests = []
function baseRequest(config) {
return new Promise((reslove, reject) => {
uni.request({
url: config.url,
method: conig.method,
header: config.header,
data: config.data,
success: res => {
if(res.code === 200){
reslove(res.data)
} else if(res.code === 401) {
// 判断是否在刷新token,如在刷新则挂起
if(isTokenRefreshing){
/* 错误写法,重新调用后无法回调到页面 */
/* failedRequests.push(() => baseRequest(config)) */
// 面向百度后改正
// 返回一个未执行resolve的promise
return new Promise(reslove => {
// 把promise的reslove保存到队列的回调里等待token刷新后调用
failedRequests.push(() => {
reslove(baseRequest(config))
})
})
}
// 更新状态
isTokenRefreshing = true
// 调用刷新token接口
refreshToken().then(res => {
store.commit('LOGIN', {
token: res.data.token,
refreshToken: res.data.refreshToken
})
// 更新状态
isTokenRefreshing = false
// 将队列中的请求使用新的token重新发送
failedRequests.forEach(callback => callback())
// 清空队列
failedRequests = []
// 再将之前 401 错误的请求重新发送
return baseRequest(config).then(res=>{
reslove(res)
})
})
}
},
fail: err => {
reject(err.data.msg)
}
})
})
}