From 5f6c1adf91d6ca61292dff94e3a29bfa19b57863 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?lemon=E6=A9=AA?= <17633066053@163.com> Date: Fri, 22 Oct 2021 18:03:41 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=97=A0=E7=97=9B=E5=88=B7?= =?UTF-8?q?=E6=96=B0token=20=E4=BF=AE=E6=94=B9=E5=88=86=E9=94=80=E6=89=AB?= =?UTF-8?q?=E7=A0=81bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- manifest.json | 4 +- pages/product/goods.vue | 4 +- pages/tabbar/home/views.vue | 33 ++++--- utils/request.js | 168 +++++++++++------------------------- 4 files changed, 77 insertions(+), 132 deletions(-) diff --git a/manifest.json b/manifest.json index b301f08..99d881d 100644 --- a/manifest.json +++ b/manifest.json @@ -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" : { diff --git a/pages/product/goods.vue b/pages/product/goods.vue index 59e4a3e..d55f275 100644 --- a/pages/product/goods.vue +++ b/pages/product/goods.vue @@ -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; } } diff --git a/pages/tabbar/home/views.vue b/pages/tabbar/home/views.vue index bd903d3..9fb5739 100644 --- a/pages/tabbar/home/views.vue +++ b/pages/tabbar/home/views.vue @@ -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,19 +128,28 @@ export default { uni.scanCode({ success: function (res) { let path = encodeURIComponent(res.result); - config.scanAuthNavigation.forEach((src) => { - if (res.result.indexOf(src) != -1) { - uni.navigateTo({ - url: `/${res.result.substring(src.length)}`, - }); - } else { - setTimeout(() => { + + // 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({ - url: "/pages/tabbar/home/web-view?src=" + path, + url: `/${res.result.substring(src.length)}`, }); - }, 100); - } - }); + } else { + setTimeout(() => { + uni.navigateTo({ + url: "/pages/tabbar/home/web-view?src=" + path, + }); + }, 100); + } + }); + } }, }); }, diff --git a/utils/request.js b/utils/request.js index 0a202de..fdfc956 100644 --- a/utils/request.js +++ b/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); + + uni.navigateTo({ + url: "/pages/passport/wechatMPLogin", + }); + // #endif // #ifndef MP-WEIXIN - debounce(() => { - uni.navigateTo({ - url: "/pages/passport/login", - }); - }, 500); + + uni.navigateTo({ + url: "/pages/passport/login", + }); + // #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) ||