记录一个刷新token时遇到的问题

133 阅读1分钟

场景:页面同时调用多个接口时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)
            }
        })
    })
}