如何在Pinia组合式API中等待异步操作完成?
问题:Pinia异步函数未正确等待,导致获取数据时出现undefined错误
我用Nuxt3、Vue3和Pinia组合式API(setup语法)创建了Pinia Store,里面包含异步函数loadWidgets。我希望在Store外部等待该函数执行完成,待widgets属性填充后再获取它,但.then()并未真正等待函数执行完毕,运行时出现Uncaught (in promise) TypeError: values is undefined错误,推测是getWidgets函数未等loadWidgets完成就返回了widgets。试过用Promise包裹加载函数但报错,求可行修改方案。
相关代码
Dashboard Store(dashboard.js)
import { defineStore } from "pinia"; import { useFetch } from "#app"; import { useAuthStore } from "./auth"; const baseUrl = import.meta.env.VITE_API_KEY + "/hr/widgets/dashboard"; export const useDashboardStore = defineStore("dashboard", () => { const authStore = useAuthStore(); const { getToken } = authStore; const widgets = ref([]); const fetchedWidgets = ref(false); async function loadWidgets() { return useFetch(baseUrl + "/list/get", { headers: { Accept: "application/json", Authorization: "Bearer " + getToken, }, onResponse({ request, response, options }) { widgets.value = response._data; fetchedWidgets.value = true; }, onResponseError({ request, response, options }) { throw showError({ statusCode: 401, statusMessage: "Error: - " + response._data, fatal: true, }); }, }); } return { widgets, loadWidgets, fetchedWidgets, }; });
组件调用代码
<script setup> import { ref } from "vue"; import { useDashboardStore } from "~/stores/dashboard"; import { useCandidatesStore } from "~/stores/candidates"; const props = defineProps({ page: { type: String, required: true, }, }); const dashboardStore = useDashboardStore(); const candidatesStore = useCandidatesStore(); onMounted(async () => { await getWidgets().then((values) => { mapWidgetsData(values); }); }); const getWidgets = async () => { switch (props.page) { case "dashboard": { const { loadWidgets, widgets, fetchedWidgets } = dashboardStore; if (!fetchedWidgets) { return await loadWidgets().then(() => { return widgets.value; }); } return widgets.value; } case "employees": { const { loadWidgets, widgets, fetchedWidgets } = candidatesStore; // 后续会实现相同逻辑,暂未完成 } } }; const mapWidgetsData = function (values) { var itemsData = values.data; layout.value = []; itemsData.forEach((value, key) => { let item = JSON.parse(value.position); item.i = value.id; item.type = value.type; layout.value.push(item); }); index.value = values.last_index + 1; }; </script>
解决方案
问题根源
useFetch返回的是Nuxt的AsyncData对象而非原生Promise,直接await loadWidgets()无法等待请求完成fetchedWidgets是ref对象,直接判断!fetchedWidgets是判断对象本身而非其值,导致逻辑错误switch未处理默认case,可能返回undefined引发后续报错
修改步骤
1. 修复Store中的loadWidgets函数
将useFetch改为直接await,让函数真正等待请求完成:
async function loadWidgets() { const { data, error } = await useFetch(baseUrl + "/list/get", { headers: { Accept: "application/json", Authorization: "Bearer " + getToken, }, }); if (error.value) { throw showError({ statusCode: 401, statusMessage: "Error: - " + error.value._data, fatal: true, }); } widgets.value = data.value; fetchedWidgets.value = true; }
2. 修复getWidgets中的ref判断与逻辑
访问ref的.value获取真实值,增加默认返回值避免undefined:
const getWidgets = async () => { switch (props.page) { case "dashboard": { const { loadWidgets, widgets, fetchedWidgets } = dashboardStore; if (!fetchedWidgets.value) { await loadWidgets(); } return widgets.value; } case "employees": { const { loadWidgets, widgets, fetchedWidgets } = candidatesStore; if (!fetchedWidgets.value) { await loadWidgets(); } return widgets.value; } default: return []; } };
3. 简化组件调用逻辑
避免async/await与.then()混用,增加值判断:
onMounted(async () => { const values = await getWidgets(); if (values) { mapWidgetsData(values); } });
可选:Store中添加getter简化数据获取
在Store中添加computed属性,避免组件直接操作ref:
export const useDashboardStore = defineStore("dashboard", () => { // ... 现有代码 const getWidgetsData = computed(() => widgets.value); return { widgets, loadWidgets, fetchedWidgets, getWidgetsData }; });
组件中可直接用dashboardStore.getWidgetsData获取数据。
内容的提问来源于stack exchange,提问作者Aleksandra
相关产品推荐
相关产品推荐

