useAsyncState - Vue 异步状态管理
通用场景:任何需要异步数据获取 + 加载状态管理的场景,核心是解决重复的模板代码问题。
具体应用:
- 表格数据加载
- 下拉选项获取
- 用户信息查询
- 搜索结果展示
- 任何需要"请求中 → 成功/失败"状态切换的组件
解决问题:标准化异步状态管理模式,避免在每个组件中重复编写 loading、error、data 三种状态的管理代码,让开发者专注业务逻辑。
避免重复代码:
js
const loading = ref(false);
const data = ref(null);
const error = ref(null);
async function fetchData() {
loading.value = true;
try {
data.value = await api();
} catch (err) {
error.value = err;
} finally {
loading.value = false;
}
}
useAsyncState.ts
typescript
import { ref as deepRef, shallowRef } from "vue";
interface useAsyncStateOptions {
args?: any[];
immediate?: boolean;
shallow?: boolean;
}
/**
* 更深层次的编写方法,可以参考一下 vueuse的useAsyncState
* @see https://vueuse.org/core/useAsyncState/
*/
export function useAsyncState(
asyncFn: (...args: any) => Promise<any>,
initialValue: any,
options: useAsyncStateOptions = {}
) {
const { args = [], immediate = true, shallow = false } = options;
const state = shallow ? shallowRef(initialValue) : deepRef(initialValue);
const loading = deepRef(false);
const error = shallowRef();
function run(...params: any[]) {
const promise = asyncFn(...params);
loading.value = true;
promise
.then((res: any) => {
state.value = res;
})
.catch((err: any) => {
error.value = err;
})
.finally(() => {
loading.value = false;
});
}
immediate && run(...args);
return {
state,
loading,
error,
run,
};
}
index.vue
vue
<script setup lang="ts">
import { ElTable } from "element-plus";
import { useAsyncState } from "./useAsyncState.ts";
async function mockFetch() {
await new Promise(resolve => setTimeout(resolve, 1000));
return [1, 2, 3, 4, 5];
}
const { state, loading } = useAsyncState(mockFetch, false);
</script>
<template>
<ElTable :loading="loading" :state="state" />
</template>