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

Nuxt3中await useAsyncData无法阻止导航,如何等待Store数据加载?

问题描述

使用Nuxt 3 + Supabase + Pinia技术栈,希望在Store数据获取并设置完成后再跳转到下一页。

当前实现代码:

  1. provider.vue(用户登录/注册后重定向页面,用于设置Cookie等):
// redirect once user has been set
const user = useSupabaseUser()
watch(user, async () => {
    if (user.value) {
        await useSteps().handleNavigateToNextStep()
    }
}, { immediate: true })
  1. app.vue中尝试用useAsyncData阻塞导航以获取Store数据:
const user = useSupabaseUser()
await useAsyncData('userStoreData', async () => {
  if (user.value) {
    await useUserStore().fetchInitialData()
  }
}, { watch: [user] })
  1. Pinia UserStore(简化版):
export const useUserStore = defineStore({
    id: 'UserStore',
    state: () => ({
        company: null as Tables<'company'> | null,
    }),
    actions: {
        async fetchInitialData() {
            const [companyData] = await Promise.all([
                useCompany().getCompany(),
            ])
            this.company = companyData;
        },
    }
})

遇到的问题:在provider.vue重定向后,通过const { company } = storeToRefs(useUserStore())获取的company值为undefined,需要让应用等待Store数据设置完成后再继续导航。


解决方案

1. 直接在provider.vue中等待Store数据初始化

当前代码中,只要user存在就立即触发跳转,但此时Store数据可能还未加载完成。修改provider.vue,确保等待数据加载完成后再执行导航:

const user = useSupabaseUser()
const userStore = useUserStore()

watch(user, async () => {
    if (user.value) {
        // 等待Store数据初始化完成
        await userStore.fetchInitialData()
        // 确认company已赋值后再跳转
        if (userStore.company) {
            await useSteps().handleNavigateToNextStep()
        }
    }
}, { immediate: true })

2. 用路由守卫全局控制导航(推荐)

通过Nuxt路由守卫拦截页面跳转,确保用户登录状态下Store数据已加载完成:
在plugins/router.ts中添加:

export default defineNuxtPlugin((nuxtApp) => {
    nuxtApp.vueApp.use((router) => {
        router.beforeEach(async (to, from) => {
            const user = useSupabaseUser()
            const userStore = useUserStore()
            
            // 仅在用户已登录、未加载Store数据、且当前不是provider页面时拦截
            if (user.value && !userStore.company && to.name !== 'provider') {
                await userStore.fetchInitialData()
            }
        })
    })
})

3. 为Store添加加载状态标记

在Store中新增加载状态,方便组件判断数据是否就绪,避免重复请求:

export const useUserStore = defineStore({
    id: 'UserStore',
    state: () => ({
        company: null as Tables<'company'> | null,
        isLoading: false
    }),
    actions: {
        async fetchInitialData() {
            // 避免重复加载
            if (this.isLoading || this.company) return
            this.isLoading = true
            
            try {
                const [companyData] = await Promise.all([
                    useCompany().getCompany(),
                ])
                this.company = companyData;
            } finally {
                this.isLoading = false
            }
        },
    }
})

在需要使用company的组件中,可通过加载状态等待数据就绪:

const userStore = useUserStore()
const { company, isLoading } = storeToRefs(userStore)

onMounted(async () => {
    if (!company.value && !isLoading.value) {
        await userStore.fetchInitialData()
    }
})

4. 优化app.vue中的useAsyncData(若保留该方案)

如果坚持使用app.vue中的useAsyncData,需确保它能真正阻塞导航,并在user变化时正确触发:

const user = useSupabaseUser()
const userStore = useUserStore()

await useAsyncData('userStoreData', async () => {
  if (user.value) {
    await userStore.fetchInitialData()
  }
}, { 
  watch: [user],
  server: false // 仅在客户端执行,避免服务端渲染时的问题
})

同时修改provider.vue,监听company状态后再跳转:

const user = useSupabaseUser()
const userStore = useUserStore()
const { company } = storeToRefs(userStore)

watch([user, company], async () => {
    if (user.value && company.value) {
        await useSteps().handleNavigateToNextStep()
    }
}, { immediate: true })

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 03:37:28