35 条回复  ·  3810 次点击
JoeJoeJoe 初学 2025-9-4 10:19:51
虽然 js 不开 worker 是单线程的, 但是你的请求是异步的, 也就是说你的刷新 token 也是异步的, 不会阻塞后续的其他请求, 在等待新 token 的时候, 其他的接口如果有返回值回来, 同样, 他们的 token 也是过期的, 也是会触发你的刷新 token 逻辑的. 比如: 现在的 token 是过期的, 同时发送了 A,B,C3 个请求 1. A 请求发送之后, 接口返回 token 过期, 然后刷新 token, 获取到新的 token, 如果这期间 B,C 还没有发出去, 那么是没有问题的. 2. A 请求发送之后, B,C 请求同时发出去了, 那么那么 BC 请求带的 token 也是过期 Token, 也会触发你说的现象. 3. A 请求发送之后, BC 请求还没有发送, A 请求收到了 token 过期的响应, 开始请求刷新 token, 这期间 BC 请求发出去了, 这种场景也会触发你说的现象. ps: 我大概猜的, 佬们轻喷
ccccccc 小成 2025-9-4 10:20:02
我建议不要搞得那么复杂,过期该重新登录就重新登录。用户根本不 care 重新登录带来的不方便,除非你几分钟就要用户登录一次
supuwoerc 楼主 小成 2025-9-4 10:24:18
@ccccccc 这个是别人的项目我帮着修 bug 的,物流程序,token 有效期只有 5 分钟,用的长短 token 方案,不断重新登录应该是要爆炸的😂
supuwoerc 楼主 小成 2025-9-4 10:25:25
@JoeJoeJoe 应该不是同时发出去,而是同时返回,同时执行到 if (!isRefreshing)的判断才会引发这个问题,我理解是这样的。
chairuosen 小成 2025-9-4 10:27:31
@irisdev 不是,他这个逻辑是在加锁的刷新线程里最后处理其他等待线程的后续,多 tab 是处理不了的,得改造一下等待的线程轮询锁自己处理后续
geelaw 小成 2025-9-4 10:27:31
@chairuosen #2 每个 tab 里都有自己的 isRefreshing 。 @crazzy #3 在 if (!isRefreshing) 和 isRefreshing = true 之间不可能有任何 JavaScript 代码执行。 @IWSR #4 这个好像是楼主代码的意思。 @supuwoerc #9 楼主可以多考虑一下读者,尝试简化代码,使之不需要借助外部语境就很容易理解,比如我们不知道 user.useLoginStore.getState() 的状态是否是 session/local 级别的,还是 tab 级别的。如果 user.useLoginStore.getState() 是 session/local 的状态,那么不同的 tab 有自己的 isRefreshing ,当然两个 tab 可以同时看到过期的 token 并分别决定刷新。 @irisdev #8 放在 local/session 都不好,因为用户可以在 tab 1 刷新的时候关闭之,但 tab 1 通过共享的 isRefreshing 锁定了刷新的权力,这会导致 local/session 清空之前不再有任何 tab 会进入刷新的逻辑。
JoeJoeJoe 初学 2025-9-4 10:27:47
@supuwoerc #13 我分析错了, 这个 isRefreshing 是个全局的, sorry.
kamilic 初学 2025-9-4 10:29:20
isRefreshing 肯定是能锁着的,都是单个线程执行的,cursor 和 copilot 说的没错。 我推测这种情况是不是并发发出的时候,出现这种情况: | ----- req1 / res1 / refresh ----- | ------------------------ isRefreshing = false ------------------------------------ | | ----- req2 ------------------------------------------------------------- | --------- res2 / isRefreshing = false ------ | 有可能你并发 req1 / req2 都是返回 10003 的,恰好 req1 刷新 token 后状态还原 isRefreshing ,req2 才返回 10003 ,那不就再刷一次喽。 是不是你的 requests 变量要再记录下在 isRefreshing = true 过程中的所有待返回请求?
supuwoerc 楼主 小成 2025-9-4 10:32:19
@geelaw 感谢大佬,user.useLoginStore.getState()是从 zustand 中读存储的 token/refresh_token 的,我复现的情况没有开多个 tab ,单独一个 tab 就偶发的出现多次刷新 token 的行为。
Niphor 小成 2025-9-4 10:32:46
F12 network 里多看看就知道拉,并发的多个请求+长短不一的响应时间 就会触发这个
返回顶部