如何让Pinia中checkAuth异步函数返回布尔值给Vue路由守卫?
认证校验函数返回Promise而非布尔值的问题解决
我在Vue+Pinia项目中搭建认证功能,编写了checkAuth异步函数用于校验用户是否已认证,期望它返回true或false并传递给路由守卫控制访问权限,但调用时发现返回的是Promise对象,无法直接拿到布尔值。
原Pinia状态存储代码
import { ref, computed, watch } from 'vue' import { defineStore } from 'pinia' import axios from 'axios' import router from '../router' axios.defaults.baseURL = 'http://localhost:4003' export const useUserStore = defineStore('user', () => { const user = ref ({ username: "", id: "", isUserLoggedin: false, email: "", authToken: "", authenticated: false, role: "" }) const checkAuth = async () => { try { await axios.post('/api/authCheck', {}, { headers: { Authorization: `Bearer ${user.value.authToken}` } }) .then(({ data: userData }) => { user.value.authenticated = true user.value.isUserLoggedin = true user.value.role = userData.user_type return true }) } catch(err) { user.value.username = "" user.value.id = "" user.value.isUserLoggedin = false user.value.email = "" user.value.authToken = "" user.value.authenticated = false user.value.role = "" router.push('/auth/login') console.log(err) return false } } return { user, checkAuth } }, { persist: true })
原路由守卫代码
router.beforeEach((to, from, next) => { // if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' }) // else next() const store = useUserStore() const authResult = store.checkAuth() console.log(authResult) if(to.meta.requiresAuth && !store.checkAuth()) next({name: 'dash.home'}) else next() })
解决方案
1. 理解异步函数的返回特性
async函数的返回值默认是Promise对象,无论内部return什么值,都会被包装成Promise。所以必须通过await或.then()来获取实际返回的布尔值。
2. 优化Pinia的checkAuth函数
统一使用await处理异步请求,避免await和.then()混合导致的逻辑混乱,同时移除store内的路由跳转,将跳转逻辑交给路由守卫:
import { ref, computed, watch } from 'vue' import { defineStore } from 'pinia' import axios from 'axios' import router from '../router' axios.defaults.baseURL = 'http://localhost:4003' export const useUserStore = defineStore('user', () => { const user = ref ({ username: "", id: "", isUserLoggedin: false, email: "", authToken: "", authenticated: false, role: "" }) const checkAuth = async () => { try { // 用await替代.then(),简化异步逻辑 const response = await axios.post('/api/authCheck', {}, { headers: { Authorization: `Bearer ${user.value.authToken}` } }) const userData = response.data user.value.authenticated = true user.value.isUserLoggedin = true user.value.role = userData.user_type return true } catch(err) { // 重置用户状态 user.value = { username: "", id: "", isUserLoggedin: false, email: "", authToken: "", authenticated: false, role: "" } console.log(err) return false } } return { user, checkAuth } }, { persist: true })
3. 修改路由守卫为异步函数
将beforeEach改为async函数,通过await获取checkAuth的返回值,再进行权限判断:
router.beforeEach(async (to, from, next) => { const store = useUserStore() // 仅调用一次checkAuth,避免重复请求 const isAuthenticated = await store.checkAuth() // 权限逻辑修正:需要认证的页面未通过校验时跳转到登录页 if (to.meta.requiresAuth && !isAuthenticated) { next({ name: 'Login' }) } else { next() } })
内容的提问来源于stack exchange,提问作者DMantas
相关产品推荐
相关产品推荐

