优化无痛刷新token 修改分销扫码bug
parent
44648e9971
commit
5f6c1adf91
|
@ -2,8 +2,8 @@
|
||||||
"name" : "lili商城",
|
"name" : "lili商城",
|
||||||
"appid" : "__UNI__C100675",
|
"appid" : "__UNI__C100675",
|
||||||
"description" : "",
|
"description" : "",
|
||||||
"versionName" : "4.0.45",
|
"versionName" : "4.0.46",
|
||||||
"versionCode" : 4000045,
|
"versionCode" : 4000046,
|
||||||
"transformPx" : false,
|
"transformPx" : false,
|
||||||
"app-plus" : {
|
"app-plus" : {
|
||||||
"compatible" : {
|
"compatible" : {
|
||||||
|
|
|
@ -483,6 +483,7 @@ export default {
|
||||||
getMpScene(this.routerVal.scene).then((res) => {
|
getMpScene(this.routerVal.scene).then((res) => {
|
||||||
if (res.data.success) {
|
if (res.data.success) {
|
||||||
let data = res.data.result.split(","); // skuId,goodsId,distributionId
|
let data = res.data.result.split(","); // skuId,goodsId,distributionId
|
||||||
|
console.warn(data)
|
||||||
this.init(data[0], data[1], data[2]);
|
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.isGroup = false; //初始化拼团
|
||||||
this.productId = id; // skuId
|
this.productId = id; // skuId
|
||||||
// 这里请求获取到页面数据 解析数据
|
// 这里请求获取到页面数据 解析数据
|
||||||
|
@ -535,6 +536,7 @@ export default {
|
||||||
if (distributionId || this.$store.state.distributionId) {
|
if (distributionId || this.$store.state.distributionId) {
|
||||||
let disResult = await getGoodsDistribution(distributionId);
|
let disResult = await getGoodsDistribution(distributionId);
|
||||||
if (!disResult.data.success || disResult.statusCode == 403) {
|
if (!disResult.data.success || disResult.statusCode == 403) {
|
||||||
|
console.log("绑定成功!")
|
||||||
this.$store.state.distributionId = distributionId;
|
this.$store.state.distributionId = distributionId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ export default {
|
||||||
* 实例化首页数据楼层
|
* 实例化首页数据楼层
|
||||||
*/
|
*/
|
||||||
init() {
|
init() {
|
||||||
this.pageData = ""
|
this.pageData = "";
|
||||||
getFloorData().then((res) => {
|
getFloorData().then((res) => {
|
||||||
if (res.data.success) {
|
if (res.data.success) {
|
||||||
this.pageData = JSON.parse(res.data.result.pageData);
|
this.pageData = JSON.parse(res.data.result.pageData);
|
||||||
|
@ -128,6 +128,14 @@ export default {
|
||||||
uni.scanCode({
|
uni.scanCode({
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
let path = encodeURIComponent(res.result);
|
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) => {
|
config.scanAuthNavigation.forEach((src) => {
|
||||||
if (res.result.indexOf(src) != -1) {
|
if (res.result.indexOf(src) != -1) {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
|
@ -141,6 +149,7 @@ export default {
|
||||||
}, 100);
|
}, 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 { md5 } from "@/utils/md5.js";
|
||||||
import Foundation from "@/utils/Foundation.js";
|
import Foundation from "@/utils/Foundation.js";
|
||||||
import api from "@/config/api.js";
|
import api from "@/config/api.js";
|
||||||
import debounce from "@/uview-ui/libs/function/debounce.js";
|
|
||||||
import uuid from "@/utils/uuid.modified.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() {
|
function cleanStorage() {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: "你的登录状态已过期,请重新登录",
|
title: "你的登录状态已过期,请重新登录",
|
||||||
|
@ -77,27 +24,28 @@ function cleanStorage() {
|
||||||
storage.setUuid("");
|
storage.setUuid("");
|
||||||
storage.setUserInfo({});
|
storage.setUserInfo({});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 防抖处理跳转
|
// 防抖处理跳转
|
||||||
// #ifdef MP-WEIXIN
|
// #ifdef MP-WEIXIN
|
||||||
debounce(() => {
|
|
||||||
console.log("防抖");
|
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: "/pages/passport/wechatMPLogin",
|
url: "/pages/passport/wechatMPLogin",
|
||||||
});
|
});
|
||||||
}, 500);
|
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// #ifndef MP-WEIXIN
|
// #ifndef MP-WEIXIN
|
||||||
debounce(() => {
|
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: "/pages/passport/login",
|
url: "/pages/passport/login",
|
||||||
});
|
});
|
||||||
}, 500);
|
|
||||||
// #endif
|
// #endif
|
||||||
}
|
}
|
||||||
|
|
||||||
let http = new Request();
|
let http = new Request();
|
||||||
const refreshToken = getTokenDebounce();
|
|
||||||
|
|
||||||
http.setConfig((config) => {
|
http.setConfig((config) => {
|
||||||
// 没有uuid创建
|
// 没有uuid创建
|
||||||
|
@ -136,26 +84,7 @@ http.interceptors.request.use(
|
||||||
config.params = params;
|
config.params = params;
|
||||||
config.header.accessToken = accessToken;
|
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 = {
|
||||||
...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(
|
http.interceptors.response.use(
|
||||||
async (response) => {
|
async (response) => {
|
||||||
|
@ -205,12 +112,39 @@ http.interceptors.response.use(
|
||||||
(token && response.statusCode === 403) ||
|
(token && response.statusCode === 403) ||
|
||||||
response.data.status === 403
|
response.data.status === 403
|
||||||
) {
|
) {
|
||||||
// jwt token 过期了
|
if (!isRefreshing) {
|
||||||
expireToken.push(token); // 把过期token 储存
|
isRefreshing = true;
|
||||||
const currentToken = storage.getAccessToken();
|
//调用刷新token的接口
|
||||||
if (expireToken.includes(currentToken)) {
|
return refreshTokenFn(storage.getRefreshToken())
|
||||||
refresh();
|
.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 (
|
} else if (
|
||||||
(!token && response.statusCode === 403) ||
|
(!token && response.statusCode === 403) ||
|
||||||
|
|
Loading…
Reference in New Issue