You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Vue Router等待App.vue中Axios请求完成后再执行?

问题描述

使用Pinia+Casl开发项目时,除页面刷新场景外功能正常。页面刷新时,Casl通过beforeEach路由守卫检查页面访问权限的操作,早于App.vue中Axios请求完成并设置Casl权限的时机,导致访问被拒绝。

相关代码如下:

App.vue中的权限初始化代码

const authStore = useAuthStore()

// 发起Axios请求的方法
authStore.setBasicAbilities()
  .catch(error => {
    console.log(error)
    authStore.logout()
  })

Main.js插件配置

app.use(abilitiesPlugin, ability, {
  useGlobalProperties: true,
})
piniaPlugin.use(({ store }) => {
  store.$router = markRaw(router)
})
app.use(piniaPlugin)
app.use(router)
app.use(layoutsPlugin)
app.use(i18n)

Router路由守卫代码

router.beforeEach(to => {
  const userStore = useUserStore(store)
  const isLoggedIn = userStore.isUserLoggedIn()
  if (canNavigate(to)) {
    if (to.meta.redirectIfLoggedIn && isLoggedIn)
      return '/'
  }
  else {
    if (isLoggedIn)
      return { name: 'not-authorized' }
    else
      return { name: 'login', query: { to: to.name !== 'index' ? to.fullPath : undefined } }
  }
})

请问如何让Vue Router等待Axios请求完成后再进行权限校验和路由跳转?


解决方案

方法1:将权限初始化逻辑移到路由守卫中

把权限请求逻辑直接整合到路由守卫里,通过异步等待确保权限设置完成后再执行校验:

// 修改后的路由守卫
router.beforeEach(async (to) => {
  const authStore = useAuthStore()
  const userStore = useUserStore(store)
  const isLoggedIn = userStore.isUserLoggedIn()

  // 已登录但权限未初始化时,先请求权限
  if (isLoggedIn && !authStore.abilitiesInitialized) {
    try {
      await authStore.setBasicAbilities()
    } catch (error) {
      console.log(error)
      authStore.logout()
      return { name: 'login', query: { to: to.fullPath } }
    }
  }

  // 原有的权限校验逻辑
  if (canNavigate(to)) {
    if (to.meta.redirectIfLoggedIn && isLoggedIn)
      return '/'
  } else {
    if (isLoggedIn)
      return { name: 'not-authorized' }
    else
      return { name: 'login', query: { to: to.name !== 'index' ? to.fullPath : undefined } }
  }
})

同时在authStore中添加状态标记权限是否初始化完成:

// useAuthStore示例
export const useAuthStore = defineStore('auth', {
  state: () => ({
    abilitiesInitialized: false,
    // 其他原有状态...
  }),
  actions: {
    async setBasicAbilities() {
      // 发起Axios请求获取权限数据
      const response = await axios.get('/api/abilities')
      // 更新Casl权限
      ability.update(response.data)
      // 标记权限初始化完成
      this.abilitiesInitialized = true
    },
    // 其他原有方法...
  }
})

方法2:在App.vue中配合导航守卫控制初始跳转

保持App.vue的权限请求逻辑,通过监听权限初始化状态让路由守卫等待:

// App.vue修改后的代码
const authStore = useAuthStore()
const router = useRouter()

async function initApp() {
  try {
    await authStore.setBasicAbilities()
  } catch (error) {
    console.log(error)
    authStore.logout()
  } finally {
    await router.isReady()
  }
}

onMounted(() => {
  initApp()
})

修改路由守卫,添加等待逻辑:

router.beforeEach((to) => {
  const authStore = useAuthStore()
  const userStore = useUserStore(store)
  const isLoggedIn = userStore.isUserLoggedIn()

  // 已登录但权限未初始化时,返回Promise等待初始化完成
  if (isLoggedIn && !authStore.abilitiesInitialized) {
    return new Promise(resolve => {
      const unwatch = watch(() => authStore.abilitiesInitialized, (initialized) => {
        if (initialized) {
          unwatch()
          resolve(to) // 重新触发当前路由的守卫校验
        }
      })
    })
  }

  // 原有的权限校验逻辑
  if (canNavigate(to)) {
    if (to.meta.redirectIfLoggedIn && isLoggedIn)
      return '/'
  } else {
    if (isLoggedIn)
      return { name: 'not-authorized' }
    else
      return { name: 'login', query: { to: to.name !== 'index' ? to.fullPath : undefined } }
  }
})

关键注意事项

  • 必须通过abilitiesInitialized状态标记权限是否设置完成,避免重复发起请求。
  • 异步路由守卫需返回Promise或使用async/await,让Vue Router等待异步操作结束。
  • 处理权限请求失败的异常,确保自动执行登出并跳转登录页。

内容的提问来源于stack exchange,提问作者Emmanuel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 12:23:16