优化无痛刷新token 修改分销扫码bug
parent
44648e9971
commit
5f6c1adf91
|
@ -2,8 +2,8 @@
|
|||
"name" : "lili商城",
|
||||
"appid" : "__UNI__C100675",
|
||||
"description" : "",
|
||||
"versionName" : "4.0.45",
|
||||
"versionCode" : 4000045,
|
||||
"versionName" : "4.0.46",
|
||||
"versionCode" : 4000046,
|
||||
"transformPx" : false,
|
||||
"app-plus" : {
|
||||
"compatible" : {
|
||||
|
|
|
@ -483,6 +483,7 @@ export default {
|
|||
getMpScene(this.routerVal.scene).then((res) => {
|
||||
if (res.data.success) {
|
||||
let data = res.data.result.split(","); // skuId,goodsId,distributionId
|
||||
console.warn(data)
|
||||
this.init(data[0], data[1], data[2]);
|
||||
}
|
||||
});
|
||||
|
@ -520,7 +521,7 @@ export default {
|
|||
/**
|
||||
* 初始化信息
|
||||
*/
|
||||
async init(id, goodsId, distributionId) {
|
||||
async init(id, goodsId, distributionId="") {
|
||||
this.isGroup = false; //初始化拼团
|
||||
this.productId = id; // skuId
|
||||
// 这里请求获取到页面数据 解析数据
|
||||
|
@ -535,6 +536,7 @@ export default {
|
|||
if (distributionId || this.$store.state.distributionId) {
|
||||
let disResult = await getGoodsDistribution(distributionId);
|
||||
if (!disResult.data.success || disResult.statusCode == 403) {
|
||||
console.log("绑定成功!")
|
||||
this.$store.state.distributionId = distributionId;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ export default {
|
|||
* 实例化首页数据楼层
|
||||
*/
|
||||
init() {
|
||||
this.pageData = ""
|
||||
this.pageData = "";
|
||||
getFloorData().then((res) => {
|
||||
if (res.data.success) {
|
||||
this.pageData = JSON.parse(res.data.result.pageData);
|
||||
|
@ -128,6 +128,14 @@ export default {
|
|||
uni.scanCode({
|
||||
success: function (res) {
|
||||
let path = encodeURIComponent(res.result);
|
||||
|
||||
// WX_CODE 为小程序码
|
||||
if (res.scanType == "WX_CODE") {
|
||||
console.log(res)
|
||||
uni.navigateTo({
|
||||
url: `/${res.path}`,
|
||||
});
|
||||
} else {
|
||||
config.scanAuthNavigation.forEach((src) => {
|
||||
if (res.result.indexOf(src) != -1) {
|
||||
uni.navigateTo({
|
||||
|
@ -141,6 +149,7 @@ export default {
|
|||
}, 100);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
|
|
156
utils/request.js
156
utils/request.js
|
@ -4,62 +4,9 @@ import storage from "@/utils/storage.js";
|
|||
import { md5 } from "@/utils/md5.js";
|
||||
import Foundation from "@/utils/Foundation.js";
|
||||
import api from "@/config/api.js";
|
||||
import debounce from "@/uview-ui/libs/function/debounce.js";
|
||||
|
||||
import uuid from "@/utils/uuid.modified.js";
|
||||
|
||||
/**
|
||||
* 无痛刷新token思路(如果不使用无痛刷新token,忽略此处注释)
|
||||
* 看了很多,有个问题一直得不到解决----‘多个接口请求,token失效,如何让获取token只获取一遍’、
|
||||
* 于是想到了闭包防抖......
|
||||
* 本方案并不是最佳方案,只是给你们提供一种思路。如果你有完美解决方案,可以分享一下
|
||||
*/
|
||||
const expireToken = []; // 储存过期的token
|
||||
|
||||
// 防抖闭包来一波
|
||||
function getTokenDebounce() {
|
||||
let lock = false;
|
||||
let success = false;
|
||||
return async function () {
|
||||
if (!lock) {
|
||||
lock = true;
|
||||
await refreshTokenFn(storage.getRefreshToken())
|
||||
.then((res) => {
|
||||
if (res.data.success) {
|
||||
let { accessToken, refreshToken } = res.data.result;
|
||||
storage.setAccessToken(accessToken);
|
||||
storage.setRefreshToken(refreshToken);
|
||||
success = true;
|
||||
lock = false;
|
||||
} else {
|
||||
cleanStorage();
|
||||
success = false;
|
||||
lock = false;
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
cleanStorage();
|
||||
success = false;
|
||||
lock = false;
|
||||
});
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
// XXX 我只能想到通过轮询来看获取新的token是否结束,有好的方案可以说。一直看lock,直到请求失败或者成功
|
||||
const timer = setInterval(() => {
|
||||
if (!lock) {
|
||||
clearInterval(timer);
|
||||
|
||||
if (success) {
|
||||
resolve("success");
|
||||
} else {
|
||||
cleanStorage();
|
||||
resolve("fail");
|
||||
}
|
||||
}
|
||||
}, 100); // 轮询时间可以自己看改成多少合适
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function cleanStorage() {
|
||||
uni.showToast({
|
||||
title: "你的登录状态已过期,请重新登录",
|
||||
|
@ -77,27 +24,28 @@ function cleanStorage() {
|
|||
storage.setUuid("");
|
||||
storage.setUserInfo({});
|
||||
|
||||
|
||||
|
||||
// 防抖处理跳转
|
||||
// #ifdef MP-WEIXIN
|
||||
debounce(() => {
|
||||
console.log("防抖");
|
||||
|
||||
uni.navigateTo({
|
||||
url: "/pages/passport/wechatMPLogin",
|
||||
});
|
||||
}, 500);
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifndef MP-WEIXIN
|
||||
debounce(() => {
|
||||
|
||||
uni.navigateTo({
|
||||
url: "/pages/passport/login",
|
||||
});
|
||||
}, 500);
|
||||
|
||||
// #endif
|
||||
}
|
||||
|
||||
let http = new Request();
|
||||
const refreshToken = getTokenDebounce();
|
||||
|
||||
|
||||
http.setConfig((config) => {
|
||||
// 没有uuid创建
|
||||
|
@ -136,26 +84,7 @@ http.interceptors.request.use(
|
|||
config.params = params;
|
||||
config.header.accessToken = accessToken;
|
||||
|
||||
/**
|
||||
* jwt 因为安卓以及ios没有window的属性
|
||||
* window.atob()这个函数 base64编码的使用方法就是btoa(),而用于解码的使用方法是atob(),
|
||||
* 所以使用手写 base-64 编码的字符串数据。
|
||||
*/
|
||||
const atob = (str) => Buffer.from(str, "base64").toString("binary");
|
||||
// 判断如果过期时间小于我的当前时间,在请求上重新刷新token
|
||||
if (accessToken.split(".").length <= 1) {
|
||||
refresh();
|
||||
} else {
|
||||
if (
|
||||
JSON.parse(
|
||||
atob(
|
||||
accessToken.split(".")[1].replace(/-/g, "+").replace(/_/g, "/")
|
||||
)
|
||||
).exp < Math.round(new Date() / 1000)
|
||||
) {
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
config.header = {
|
||||
...config.header,
|
||||
|
@ -168,33 +97,11 @@ http.interceptors.request.use(
|
|||
}
|
||||
);
|
||||
|
||||
async function refresh() {
|
||||
// 本地储存的是过期token了,重新获取
|
||||
const getTokenResult = await refreshToken();
|
||||
if (getTokenResult === "success") {
|
||||
// 获取新的token成功 刷新当前页面
|
||||
|
||||
let routes = getCurrentPages(); // 获取当前打开过的页面路由数组
|
||||
let curRoute = routes[routes.length - 1].route; //获取当前页面路由
|
||||
let curParam = routes[routes.length - 1].options; //获取路由参数
|
||||
// 拼接参数
|
||||
let param = "";
|
||||
for (let key in curParam) {
|
||||
param += "&" + key + "=" + curParam[key];
|
||||
}
|
||||
// 判断当前路径
|
||||
if (curRoute.indexOf("pages/tabbar") == 1) {
|
||||
uni.switchTab({
|
||||
url: "/" + curRoute + param.replace("&", "?"),
|
||||
});
|
||||
}
|
||||
|
||||
uni.redirectTo({
|
||||
url: "/" + curRoute + param.replace("&", "?"),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 是否正在刷新的标记
|
||||
let isRefreshing = false;
|
||||
//重试队列
|
||||
let requests = [];
|
||||
// 必须使用异步函数,注意
|
||||
http.interceptors.response.use(
|
||||
async (response) => {
|
||||
|
@ -205,12 +112,39 @@ http.interceptors.response.use(
|
|||
(token && response.statusCode === 403) ||
|
||||
response.data.status === 403
|
||||
) {
|
||||
// jwt token 过期了
|
||||
expireToken.push(token); // 把过期token 储存
|
||||
const currentToken = storage.getAccessToken();
|
||||
if (expireToken.includes(currentToken)) {
|
||||
refresh();
|
||||
if (!isRefreshing) {
|
||||
isRefreshing = true;
|
||||
//调用刷新token的接口
|
||||
return refreshTokenFn(storage.getRefreshToken())
|
||||
.then((res) => {
|
||||
let { accessToken, refreshToken } = res.data.result;
|
||||
storage.setAccessToken(accessToken);
|
||||
storage.setRefreshToken(refreshToken);
|
||||
|
||||
response.header.accessToken = `${accessToken}`;
|
||||
// token 刷新后将数组的方法重新执行
|
||||
requests.forEach((cb) => cb(accessToken));
|
||||
requests = []; // 重新请求完清空
|
||||
return http.request(response.config);
|
||||
})
|
||||
.catch((err) => {
|
||||
cleanStorage();
|
||||
return Promise.reject(err);
|
||||
})
|
||||
.finally(() => {
|
||||
isRefreshing = false;
|
||||
});
|
||||
} else {
|
||||
// 返回未执行 resolve 的 Promise
|
||||
return new Promise((resolve) => {
|
||||
// 用函数形式将 resolve 存入,等待刷新后再执行
|
||||
requests.push((token) => {
|
||||
response.header.accessToken = `${token}`;
|
||||
resolve(http.request(response.config));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 如果当前返回没登录
|
||||
} else if (
|
||||
(!token && response.statusCode === 403) ||
|
||||
|
|
Loading…
Reference in New Issue