uniapp无痛刷新token继续网络请求

原创
08/04 13:44
阅读数 1K

uniapp无痛刷新token继续网络请求

更新时间:2020-08-05 08:46

一.问题场景

用户请求后台用到两个token,一个是access_token,另一个是refresh_token.当access_token过期之后,需要使用refresh_token去后台请求新的access_token,然后拿着新的access_token继续后面的网络请求.

二.解决方案

二.一解决思路

1.本地过期时间校验;

2.请求token的请求用Promise形式包裹;

3.继续之前被打断的网络请求,将该网络请求修改成同步形式用到async和await,并在success方法中调用Promise中的resolve(res),将获取到的数据借助Promise返回;

二.二实现方案

1.用户成功登陆之后,将用户登录的时间和token过期时间记录下来,或者是记录后台返回的过期时间;

2.在封装的请求中,每次请求校验当前时间和过期时间之间的差值,如果"过期时间"-"当前时间"=时间差值>=10分钟(这个时间可以自己定义),则直接继续网络请求;如果时间差值<10分钟,则在发送该次网络请求之间先发送刷新access_token的请求,得到新的token再继续之前的网络请求;

3.发送刷新token的网络请求请使用Promise模式包裹,因为我个人封装的uniapp请求库是Promise模式的(参考链接:https://my.oschina.net/u/3943503/blog/4328562),需要返回一个Promise;

4.将正常的数据请求修改成同步模式用到async和await,然后调用该方法,在uni.request的success方法中调用resolve(res),将数据返回给页面上的请求,实现数据的正常接收和处理.

刷新的网络请求修改成同步,请参考这个博客:https://www.jianshu.com/p/8555a8451101

核心示例代码:

request(option) {
        option.url = option.url || CONFIG.url;
        option.header = option.header || CONFIG.header;
        option.header["Authorization"] = uni.getStorageSync("token_type") + " " + uni.getStorageSync("access_token");
        option.data = option.data || CONFIG.url;
        option.method = option.method || CONFIG.method;
        option.dataType = option.dataType || CONFIG.dataType;
        let expiration = uni.getStorageSync('expiration');
        // console.log();
        // 时间格使用2020/10/10 12:00:00这种格式计算
        let tmp = expiration.replace(/-/g, "/");
        // console.log(tmp);
        let futureTime = new Date(tmp).valueOf();//转换成毫秒
        // console.log(futureTime);
        let nowTime = new Date().valueOf();//转换成毫秒
        // console.log(nowTime);
        let jetLag = (futureTime - nowTime)/1000/60/60;
        // let jetLag = (futureTime - nowTime) / 1000;
        console.log(jetLag);
        if (jetLag < 0.1) {
            let appStr = "test:Hbgc_test@001",
                wordArray = CryptoJS.enc.Utf8.parse(appStr),
                appBase64 = CryptoJS.enc.Base64.stringify(wordArray),
                header = {
                    "Authorization": "Basic " + appBase64,
                    "Content-type": "application/x-www-form-urlencoded"
                },
                data = {
                    "grant_type": "refresh_token",
                    "refresh_token": uni.getStorageSync("refresh_token")
                };
            return new Promise((resolve, reject) => {
                uni.request({
                    url: Api.HOST + Api.LOGIN,
                    data: data,
                    header: header,
                    method: "POST",
                    success(res) {
                        // console.log(res2.statusCode);
                        if (res.statusCode == 401) {
                            uni.showToast({
                                icon: "none",
                                title: "用户未认证或登录过期,请重新登录"
                            });
                            setTimeout(function() {
                                uni.reLaunch({
                                    url: "/pages/login/login"
                                });
                            }, 1000);
                        } else {
                            uni.setStorageSync("expiration", res.data.expiration);
                            uni.setStorageSync("expires_in", res.data.expires_in);
                            uni.setStorageSync("access_token", res.data.access_token);
                            uni.setStorageSync("id", res.data.id);
                            uni.setStorageSync("real_name", res.data.real_name);
                            uni.setStorageSync("refresh_token", res.data.refresh_token);
                            uni.setStorageSync("scope", res.data.scope);
                            uni.setStorageSync("token_type", res.data.token_type);
                            option.header = option.header || CONFIG.header;
                            option.header["Authorization"] = uni.getStorageSync("token_type") + " " +uni.getStorageSync("access_token");
                            
                            requestIn();
                            
                            async function requestIn(){
                                let [err2,res2] = await uni.request({
                                    header: option.header,
                                    url: option.url,
                                    data: option.data,
                                    method: option.method,
                                    dataType: option.dataType,
                                });
                                uni.hideLoading();
                                if(res2.statusCode === 200){
                                    resolve(res2);
                                }else{
                                    uni.showToast({
                                        icon:"none",
                                        title:"状态码:"+res2.statusCode+"."+res2.data.message
                                    });
                                    return;
                                }
                                resolve(res2);
                                uni.showToast({
                                    icon:"none",
                                    title:"状态码:"+err2.statusCode+"."+err2.data.message
                                });
                            }
                            
                        }
                    },
                    fail(err) {
                        reject(err);
                        console.log("err:" + JSON.stringify(err));
                    }
                });
            });
        } else {
            option.header = option.header || CONFIG.header;
            option.header["Authorization"] = uni.getStorageSync("token_type") + " " + uni.getStorageSync("access_token");
            return new Promise((resolve, reject) => {
                uni.request({
                    header: option.header,
                    url: option.url,
                    data: option.data,
                    method: option.method,
                    dataType: option.dataType,
                    success(res) {
                        // console.log(JSON.stringify(res));
                        if(res.statusCode === 200){
                            resolve(res);
                        }else{
                            uni.showToast({
                                icon:"none",
                                title:"状态码:"+res.statusCode+"."+res.data.message
                            });
                        }
                    },
                    fail(err) {
                        uni.showToast({
                            icon:"none",
                            title:"状态码:"+err.statusCode+"."+err.data.message
                        });
                        reject(err);
                    }
                });
            });
        }
    },

说明:这里只是提供了思路和核心示例代码,仅供参考.

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部