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

Vue3 Composition API的setup内封装Axios请求返回Promise问题求解

问题原因

你第一种写法返回Promise的核心原因是async函数的返回值天生为Promise类型,而setup函数是同步执行的,不会等待异步请求完成再进行赋值,所以直接将getInvoices()的返回值赋值给invoices属性,拿到的自然是未完成的Promise对象,而非实际接口返回的数据。

组件内可复用封装方案

如果仅需要在当前组件内复用请求逻辑,直接把数据赋值逻辑放到封装的函数内部即可,不需要依赖函数返回值赋值,后续要新增过滤、刷新功能直接调用封装好的函数即可:

export default {
    components: {Loader, PageBase},
    props: {
        fetch_url: {
            required: true,
            type: String,
        }
    },
    setup(props) {
        const loading = ref(false)
        const state = reactive({
            invoices: [],
            selectedInvoices: [],
            filters: {} // 后续过滤参数可存储在此
        });

        // 封装可复用请求函数,支持传入过滤参数
        async function getInvoices(params = {}) {
            loading.value = true;
            try {
                const response = await axios.get(props.fetch_url, { params })
                state.invoices = response.data.data
            } catch (err) {
                // 可在此处添加全局错误提示逻辑
                console.error('拉取数据失败', err)
            } finally {
                loading.value = false
            }
        }

        // 页面首次加载时调用
        getInvoices()

        // 过滤参数变化时调用示例
        function handleFilterChange(newFilters) {
            state.filters = newFilters
            getInvoices(newFilters)
        }

        function handleSelectionChange(selection) {
            state.selectedInvoices = selection;
        }

        return {
            loading,
            state,
            handleSelectionChange,
            handleFilterChange
        }
    }
}

跨组件通用复用方案

如果需要在多个业务组件复用列表拉取逻辑,可以将请求逻辑抽为Vue3标准的逻辑复用单元——自定义Composable:

  1. 新建composables/useFetchList.js文件,编写通用逻辑:
import { ref } from 'vue'
import axios from 'axios'

export function useFetchList(fetchUrl) {
    const loading = ref(false)
    const list = ref([])
    const error = ref(null)

    async function fetch(params = {}) {
        loading.value = true
        error.value = null
        try {
            const response = await axios.get(fetchUrl, { params })
            list.value = response.data.data
        } catch (err) {
            error.value = err
        } finally {
            loading.value = false
        }
    }

    return {
        loading,
        list,
        error,
        fetch
    }
}
  1. 在业务组件中直接调用即可:
import { useFetchList } from '@/composables/useFetchList'
import { reactive } from 'vue'

export default {
    components: {Loader, PageBase},
    props: {
        fetch_url: {
            required: true,
            type: String,
        }
    },
    setup(props) {
        // 调用通用Composable,解构出需要的属性和方法
        const { loading, list: invoices, fetch: getInvoices } = useFetchList(props.fetch_url)
        const state = reactive({
            selectedInvoices: [],
        })

        // 首次加载拉取数据
        getInvoices()

        function handleSelectionChange(selection) {
            state.selectedInvoices = selection;
        }

        return {
            loading,
            invoices,
            state,
            getInvoices,
            handleSelectionChange,
        }
    }
}

补充说明

你当前使用的InertiaJS官方内置了form辅助工具,本身已经封装了请求状态管理、参数传递等能力,如果不需要兼容旧的Axios封装逻辑,也可以直接使用官方能力简化代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 18:24:05