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:
- 新建
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 } }
- 在业务组件中直接调用即可:
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
相关产品推荐
相关产品推荐

