Vben5 token 过期后页面点不动,是并发 401 竞态

2026年4月27日

现象

token 过期时 dashboard 同时发起多个请求,全部返回 401。页面没有可见蒙版,但所有点击都失效。

根因

doReAuthenticate() 默认没有并发幂等保护。N 个并发 401 会触发 N 次登出流程,每次都会 resetAllStores()router.replace(LOGIN_PATH)。竞态后果是 Pinia 多次清空导致渲染中的组件取到空值抛错,多个路由导航互相打断,而 Modal 的 backdrop 来不及随 v-model 卸载就被强制 reset,留下一个高 z-index 的透明 div 挡住所有点击。

修复

用 Promise 缓存包一层,保证并发只跑一次。

let reAuthenticatePromise: Promise<void> | null = null;

async function doReAuthenticate() {
  if (reAuthenticatePromise) return reAuthenticatePromise;
  reAuthenticatePromise = (async () => {
    // 原有逻辑
  })().finally(() => {
    reAuthenticatePromise = null;
  });
  return reAuthenticatePromise;
}

排查方法

打开 F12 的 Elements 面板搜 mask,或者看 body > div 里有没有 z-index 大于 1000 的透明 div。Network 面板看是否一波 401 同时返回。

vben5前端踩坑