# 源码
import { ComputedRef, WatchSource, reactive, toRefs, watch } from "vue";
export interface Options<T, P extends any[]> {
// 是否手动发起请求
manual?: boolean;
// 当 manual 为false时,自动执行的默认参数
defaultParams?: P;
// 依赖项更新
refreshDeps?: WatchSource<any>[];
refreshDepsParams?: ComputedRef<P>;
// 并发请求
queryKey?: (...args: P) => string;
// 成功回调
onSuccess?: (response: T, params: P) => void;
// 失败回调
onError?: (err: any, params: P) => void;
}
export interface IRequestResult<T> {
data: T | null;
loading: boolean;
err?: any;
}
const defaultQuerise = Symbol("default"); // 默认为非 queryKey 维护的普通请求
export function useRequest<T, P extends any[]>(
service: (...args: P) => Promise<T>,
options: Options<T, P> = {},
) {
const {
manual = false,
defaultParams = [] as unknown as P,
refreshDeps = null,
refreshDepsParams = null,
queryKey = null,
onSuccess,
onError,
} = options;
const querise = reactive<Record<string | symbol, IRequestResult<T>>>({
[defaultQuerise]: {
data: null,
loading: false,
err: undefined,
},
});
const serviceFn = async (...args: P) => {
const key = queryKey ? queryKey(...args) : defaultQuerise;
if (!querise[key]) {
querise[key] = {} as any;
}
querise[key].loading = true;
service(...args)
.then((res) => {
querise[key].data = res;
querise[key].err = undefined;
onSuccess && onSuccess(res, args);
})
.catch((err: any) => {
querise[key].err = err;
onError && onError(err, args);
})
.finally(() => {
querise[key].loading = false;
});
};
const run = serviceFn;
// 依赖更新
if (refreshDeps) {
watch(
refreshDeps,
() => {
run(...(refreshDepsParams?.value || ([] as unknown as P)));
},
{ deep: true },
);
}
if (!manual) {
run(...defaultParams);
}
return {
run,
querise,
...toRefs(querise[defaultQuerise]),
};
}
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
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
# 使用
1.手动执行
const {data,loading,run}=useRequest(somePromise,{manual:true})
const somePromise=()=>{
return new Promise((resolve, reject)=>{
resolve('请求成功')
})
}
run()
1
2
3
4
5
6
7
2
3
4
5
6
7
2.自动执行一次并带默认参数
const {data,loading}=useRequest(somePromise,{
defaultParams: [
{
params1: '参数1',
params2: '参数2',
},
]})
const somePromise=(params1,params2)=>{
return new Promise((resolve, reject)=>{
resolve(params1,params2)
})
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
3.监听响应式数据并自动执行更新数据
const pages = reactive({
limit: 5,
page: 1,
loadingEnd: false,
});
const params:ComputedRef<[{page:number,limit:number}]> = computed(() => [
{
page: pages.page,
limit: pages.limit,
},
]);
const { data,loading} = useRequest(searchReviews, {
refreshDeps: [() => pages.page],
refreshDepsParams: params,
defaultParams: [
{
page: pages.page,
limit: pages.limit,
},
],
onSuccess: (response, params) => {
if (response.data.length == 0) {
pages.loadingEnd = true;
}
},
onError: (err)=>{
console.log(err)
}
});
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
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