如何让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
相关产品推荐
相关产品推荐

