微信小程序实现无感刷新token,接口缓存队列

微信小程序实现无感刷新token,接口缓存队列

需求

token过期的时候,刷新token,前端需要做到无感刷新token,即刷token时要做到用户无感知,避免频繁登录,当同时发起两个或者两个以上的请求时,防止多次刷新token,其他接口获取到新的token后继续执行请求操作

问题解决

当第二个过期的请求进来,token正在刷新,我们先将这个请求存到一个数组队列中,想办法让这个请求处于等待中,一直等到刷新token后再逐个重试清空请求队列。
那么如何做到让这个请求处于等待中呢?为了解决这个问题,我们得借助Promise。将请求存进队列中后,同时返回一个Promise,让这个Promise一直处于Pending状态(即不调用resolve),此时这个请求就会一直等啊等,只要我们不执行resolve,这个请求就会一直在等待。当刷新请求的接口返回来后,我们再调用resolve,逐个重试。最终代码:


let isRefreshing = false// 是否正在刷新的标记
let requests = []//重试队列
let ajaxtimes = 0;//同时发送异步代码次数
function cloudRrequest(paramsList) {
    
    
	let _this = this;
    let params = JSON.parse(JSON.stringify(paramsList))
    ajaxtimes++;
    params.url =xxx+ params.url,//这里自己封装接口
    if (!params.data) {
    
    //参数
        params.data = {
    
    }
    }
    if (!params.header) {
    
    //请求头
        params.header = {
    
    }
    }
    if (params.data.token) {
    
    //是否传入了token
        console.log("token~~~~~");
    } else if (getTokenSync) {
    
    //缓存token存在则赋值
        params.data.token = getTokenSync
    }
    return new Promise((resolve, reject) => {
    
    
        wx.request({
    
    
            ...params,
            method: params.method || "GET",
            success: function(res) {
    
    
                if (res.statusCode == 200) {
    
    //http状态码是否成功
                    var data = res.data;
                    if (data.code != 200) {
    
     //后端返回的状态码是否成功
                        if (data.code == 403) {
    
     //当token过期执行
                        //这里是重点:让这个Promise一直处于Pending状态(即不调用resolve)
                            new Promise(resolve2 => {
    
    
                                // 用函数形式将 resolve 存入,等待刷新后再执行
                                requests.push(token => {
    
    
                                    // params.headers.Authorization = `${token}`
                                    if (!paramsList.data) {
    
    
                                        paramsList.data = {
    
    }
                                    }
                                    paramsList.data.token = `${
      
      token}`
                                    //这里resolve
                                    resolve(_this.cloudRrequest(paramsList, messages))
                                })
                            })
                            if (!isRefreshing) {
    
     //成功状态
                                console.log("token过期");
                                isRefreshing = true//第一个请求后,后面请求都不进入执行请求
                                    //调用刷新token的接口
                                return _this.cloudRrequest({
    
    
                                    url: 'refreshToken',
                                    data: {
    
     refreshToken: wx.getStorageSync('refreshToken') },
                                    method: 'POST'
                                }).then((data) => {
    
    
                                    console.log(data);
                                    if (data.token) {
    
    
                                        wx.setStorageSync('token', data.token);
                                        // response.headers.Authorization = `${token}`
                                        // token 刷新后将数组的方法重新执行
                                        requests.forEach((cb) => cb(data.token))
                                        requests = [] // 重新请求完清空
                                        return
                                    }
                                }).catch(err => {
    
    
                                    //获取token失败,删除旧token,跳到登录页
                                     try {
    
    
                                         wx.removeStorageSync('token')
                                     } catch (error) {
    
    }
                                     wx.reLaunch({
    
    
                                         url: '/pages/login/login'
                                     })
                                    return Promise.reject(err)
                                })
                            }
                        }  else {
    
     //其他错误
                            wx.showModal({
    
    
                                title: '提示',
                                content: data.message,
                            });
                        }
                    } else {
    
     //请求成功时直接返回数据
                        resolve(data.data);
                    }
                } else {
    
     //其他错误
                    wx.showModal({
    
    
                        title: '提示',
                        content: res.data.message,
                    });
                }
            },
            fail: function(err) {
    
    
                console.log();
                reject(err)
            },
            complete: function() {
    
    
                ajaxtimes--
                //当执行请求最后一个请求后关闭加载动画
                if (ajaxtimes === 0) {
    
    
                    wx.hideNavigationBarLoading()//在当前页面隐藏导航条加载动画
                    wx.stopPullDownRefresh() //停止当前页面下拉刷新。
                }
            },
        })
    })
}
module.exports = {
    
    
    cloudRrequest: cloudRrequest,
}

这里参考了
https://juejin.cn/post/6983582201690456071#heading-4
使用axios实现无感刷新的案例

猜你喜欢

转载自blog.csdn.net/weixin_44982333/article/details/120135626