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

如何在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>

解决方案

问题根源

  1. useFetch返回的是Nuxt的AsyncData对象而非原生Promise,直接await loadWidgets()无法等待请求完成
  2. fetchedWidgets是ref对象,直接判断!fetchedWidgets是判断对象本身而非其值,导致逻辑错误
  3. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 18:53:13