useAsyncState并不是Vue.js的原生API,而是一些第三方库提供的自定义hook,用于简化在Vue组件中处理异步操作的过程,如发送网络请求、加载数据或执行其他耗时的任务。
实现
import { toRefs, reactive, onMounted } from "vue";
/**
* useAsync
* @param {Promise} pro 异步操作
* @param {Object} options 参数
* @param {Boolean} [options.manual=false] 是否手动调用
* @param {Any} options.initialData 初始化数据
* @param {Function} options.onSuccess 成功回调
* @param {Function} options.onError 失败回调
*/
export function useAsync(pro, options = {}) {
const {
manual = false,
initialData,
onSuccess = () => {},
onError = console.log,
} = options;
const state = reactive({
data: initialData || null,
error: null,
loading: false,
});
const run = async () => {
state.error = null;
state.loading = true;
try {
const result = await pro();
state.data = result;
onSuccess();
} catch (err) {
onError(err);
state.error = err;
} finally {
state.loading = false;
}
};
onMounted(() => {
!manual && run();
});
// 从外部主动改变数据
function mutate(data) {
state.data = data;
}
return {
...toRefs(state),
run,
mutate,
};
}
使用
<template>
<div v-if="listLoading">Loading...</div>
<div v-else-if="state">Data: {{ state }}</div>
<button @click="getList">run</button>
</div>
</template>
<script setup>
const {
data: listData,
loading: listLoading,
run: getList,
} = useAsync(() => API.getList({
flag: 1,
pageNo: 0,
pageSize: 20,
}), { initialData: {}, manual: true });
</script>