-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Expand file tree
/
Copy pathuseAsyncData.ts
More file actions
111 lines (98 loc) · 2.59 KB
/
Copy pathuseAsyncData.ts
File metadata and controls
111 lines (98 loc) · 2.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import { ref, watch, type Ref, type ComputedRef } from 'vue'
import type { TimeFilter } from '@openchatlab/shared-types'
/**
* 异步数据加载 Composable
* 统一处理数据加载、状态管理和错误处理
*/
interface UseAsyncDataOptions<T> {
/** 是否立即加载数据(默认 true) */
immediate?: boolean
/** 是否深度监听 timeFilter(默认 true) */
deep?: boolean
/** 加载失败时的错误处理 */
onError?: (error: Error) => void
/** 默认值 */
defaultValue?: T
}
interface UseAsyncDataReturn<T> {
/** 数据 */
data: Ref<T | null>
/** 是否正在加载 */
isLoading: Ref<boolean>
/** 错误信息 */
error: Ref<Error | null>
/** 重新加载 */
reload: () => Promise<void>
}
/**
* 通用异步数据加载 composable
* @param fetchFn 数据获取函数
* @param sessionId 会话 ID(响应式)
* @param timeFilter 时间筛选条件(可选,响应式)
* @param options 配置选项
*/
export function useAsyncData<T>(
fetchFn: (sessionId: string, timeFilter?: TimeFilter) => Promise<T>,
sessionId: Ref<string> | ComputedRef<string>,
timeFilter?: Ref<TimeFilter | undefined> | ComputedRef<TimeFilter | undefined>,
options: UseAsyncDataOptions<T> = {}
): UseAsyncDataReturn<T> {
const { immediate = true, deep = true, onError, defaultValue } = options
const data = ref<T | null>(defaultValue ?? null) as Ref<T | null>
const isLoading = ref(false)
const error = ref<Error | null>(null)
async function load() {
const sid = sessionId.value
if (!sid) return
isLoading.value = true
error.value = null
try {
data.value = await fetchFn(sid, timeFilter?.value)
} catch (e) {
const err = e instanceof Error ? e : new Error(String(e))
error.value = err
if (onError) {
onError(err)
} else {
console.error('数据加载失败:', err)
}
} finally {
isLoading.value = false
}
}
// 监听 sessionId 和 timeFilter 变化
watch(
() => [sessionId.value, timeFilter?.value],
() => {
if (sessionId.value) {
load()
}
},
{ immediate, deep }
)
return {
data,
isLoading,
error,
reload: load,
}
}
/**
* 批量加载多个异步数据
* @param loaders 加载函数数组
*/
export function useMultipleAsyncData(loaders: Array<() => Promise<void>>) {
const isLoading = ref(false)
async function loadAll() {
isLoading.value = true
try {
await Promise.all(loaders.map((loader) => loader()))
} finally {
isLoading.value = false
}
}
return {
isLoading,
loadAll,
}
}