Skip to content

Commit c4b762e

Browse files
author
zuofenghua
committed
feat: useRequest support ready
1 parent a77ef4f commit c4b762e

File tree

11 files changed

+221
-53
lines changed

11 files changed

+221
-53
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ahooks-vue",
3-
"version": "0.12.3",
3+
"version": "0.12.4",
44
"description": "ahooks-vue",
55
"types": "dist/src/index.d.ts",
66
"repository": "https://github.com/dewfall123/ahooks-vue.git",

src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,3 @@ export * from './useThrottle';
1616
export * from './useToggle';
1717
export * from './useUrlState';
1818
export * from './useWorkerFunction';
19-

src/useRequest/__test__/options.spec.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,4 +282,59 @@ describe('useRequest - options', () => {
282282
await sleep(100);
283283
expect(loading.value).toEqual(true);
284284
});
285+
286+
it('should ready work when manual = false', async () => {
287+
const ready = ref(false);
288+
const { loading } = useRequest(getFullName, {
289+
ready,
290+
manual: false,
291+
});
292+
expect(loading.value).toEqual(false);
293+
294+
await nextTickInFakeTimers();
295+
ready.value = true;
296+
297+
await nextTickInFakeTimers();
298+
expect(loading.value).toEqual(true);
299+
});
300+
301+
it('should ready work when manual = false', async () => {
302+
const ready = ref(true);
303+
const { loading } = useRequest(getFullName, {
304+
ready,
305+
manual: false,
306+
});
307+
await nextTickInFakeTimers();
308+
expect(loading.value).toEqual(true);
309+
});
310+
311+
it('should ready work when manual = true', async () => {
312+
const ready = ref(false);
313+
const { loading, run } = useRequest(getFullName, {
314+
ready,
315+
manual: true,
316+
});
317+
318+
expect(loading.value).toEqual(false);
319+
run();
320+
await nextTickInFakeTimers();
321+
expect(loading.value).toEqual(false);
322+
323+
ready.value = true;
324+
await nextTickInFakeTimers();
325+
expect(loading.value).toEqual(false);
326+
327+
run();
328+
await nextTickInFakeTimers();
329+
expect(loading.value).toEqual(true);
330+
331+
jest.advanceTimersByTime(getFullNameTime);
332+
await nextTickInFakeTimers();
333+
expect(loading.value).toEqual(false);
334+
335+
ready.value = false;
336+
run();
337+
await nextTickInFakeTimers();
338+
expect(loading.value).toEqual(false);
339+
});
285340
});

src/useRequest/constants.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { ref } from 'vue-demi';
12
import { UseRequestOptions } from './types';
23

34
function fetchProxy(params: string | Record<string, string>) {
@@ -38,7 +39,7 @@ export const DefaultOptions = {
3839
loadingWhenDebounceStart: true,
3940
throttleInterval: 0,
4041
initialData: undefined,
41-
// ready: true,
42+
ready: ref(true),
4243
throwOnError: false,
4344
refreshDeps: [],
4445
refreshOnWindowFocus: false,
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<template>
2+
<div>
3+
<div>
4+
<button @click="toggle()">toggle-ready</button>
5+
<span style="margin-left: 8px;">ready: {{ ready }}</span>
6+
</div>
7+
<p>
8+
UserName: <span>{{ loading ? 'loading' : data }}</span>
9+
</p>
10+
<button @click="run()">run</button>
11+
</div>
12+
</template>
13+
14+
<script lang="ts" setup>
15+
import { useRequest, useToggle } from 'ahooks-vue';
16+
import { getFullName } from './utils';
17+
18+
const { state: ready, toggle } = useToggle();
19+
20+
const { data, loading, run } = useRequest(getFullName, {
21+
manual: true,
22+
ready,
23+
});
24+
</script>

src/useRequest/demo/demo-ready.vue

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<template>
2+
<div>
3+
<div>
4+
<button @click="toggle()">toggle-ready</button>
5+
<span style="margin-left: 8px;">ready: {{ ready }}</span>
6+
</div>
7+
<p>
8+
UserName: <span>{{ loading ? 'loading' : data }}</span>
9+
</p>
10+
<button @click="run()">run</button>
11+
</div>
12+
</template>
13+
14+
<script lang="ts" setup>
15+
import { useRequest, useToggle } from 'ahooks-vue';
16+
import { getFullName } from './utils';
17+
18+
const { state: ready, toggle } = useToggle();
19+
20+
const { data, loading, run } = useRequest(getFullName, {
21+
manual: false,
22+
ready,
23+
});
24+
</script>

src/useRequest/index.en-US.md

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,22 @@ The API is different from [ahooks](https://ahooks.js.org/hooks/async).
6969
desc="Setting `options.loadingDelay` can specifies a delay in milliseconds for loading (prevent flush).">
7070
</demo>
7171

72+
### Ready
73+
74+
<demo src="./demo/demo-ready.vue"
75+
language="vue"
76+
title="Ready"
77+
desc="In the automatic mode of manual=false, every time ready changes from false to true, a request will be automatically executed with the parameter options.defaultParams">
78+
</demo>
79+
80+
### Ready (manual = true)
81+
82+
<demo src="./demo/demo-ready-manual-true.vue"
83+
language="vue"
84+
title="Ready"
85+
desc="When manual=true manual request mode, as long as ready=false, the request triggered by run will not be executed">
86+
</demo>
87+
7288
## Basic API
7389

7490
```javascript
@@ -124,21 +140,22 @@ const {
124140

125141
All Options are optional.
126142

127-
| Property | Description | Type | Default |
128-
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------- | ------- |
129-
| manual | <ul><li> The default `false`. That is, the service is automatically executed during initialization.</li><li>If set to `true`, you need to call `run` manually to trigger execution. </li></ul> | `boolean` | false |
130-
| initialData | initial data | `any` | - |
131-
| formatResult | Format request results | `(response: any) => any` | - |
132-
| onSuccess | <ul><li> Triggered when the service resolved, the parameters are `data` and`params` </li><li> If `formatResult` is present,`data` is the formatted data.</li></ul> | `(data: any, params: any[]) => void` | - |
133-
| onError | Triggered when the service reports an error. The parameters are `error` and`params`. | `(error: Error, params: any[]) => void` | - |
134-
| defaultParams | If `manual = false`, the default parameters when run is executed automatically, | `any[]` | - |
135-
| loadingDelay | Set delay time for display loading to avoid flicker | `number` | - |
136-
| pollingInterval | Polling interval in milliseconds. After setting, it will enter polling mode and trigger `run` periodically. | `number` | - |
137-
| pollingSinceLastFinished | <ul><li> Whether start next polling request since last request finished. Default is `true`. </li><li> If set `false`, request will start every `pollingInterval` time. </li></ul> | `boolean` | true |
138-
| pollingWhenHidden | <ul><li> Whether to continue polling when the page is hidden. Default is `true`, that is, polling will not stop </li><li> If set to `false`, polling is temporarily stopped when the page is hidden, and the last polling is continued when the page is redisplayed </li></ul> | `boolean` | `true` |
139-
| debounceInterval | debounce interval, the unit is millisecond. After setting, request to enter debounce mode. | `number` | - |
140-
| loadingWhenDebounceStart | Whether set loading to `true` when the `run` function starts to execute. | `boolean` | `true` |
141-
| throttleInterval | throttle interval, the unit is millisecond. After setting, request to enter throttle mode. | `number` | - |
142-
| throwOnError | If the service errors, the error will only be logged. If you want an error to be thrown, pass the throwOnError: true | `boolean` | `false` |
143-
| refreshOnWindowFocus `v0.9` | The request will be re-initiated when the screen is refocused or revisible. | `boolean` | `false` |
144-
| refreshDeps `v0.9` | RefreshDeps changes will trigger the service to re-execute. | `WatchSource[]` | `[]` |
143+
| Property | Description | Type | Default |
144+
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------- | ----------- |
145+
| manual | <ul><li> The default `false`. That is, the service is automatically executed during initialization.</li><li>If set to `true`, you need to call `run` manually to trigger execution. </li></ul> | `boolean` | false |
146+
| initialData | initial data | `any` | - |
147+
| formatResult | Format request results | `(response: any) => any` | - |
148+
| onSuccess | <ul><li> Triggered when the service resolved, the parameters are `data` and`params` </li><li> If `formatResult` is present,`data` is the formatted data.</li></ul> | `(data: any, params: any[]) => void` | - |
149+
| onError | Triggered when the service reports an error. The parameters are `error` and`params`. | `(error: Error, params: any[]) => void` | - |
150+
| defaultParams | If `manual = false`, the default parameters when run is executed automatically, | `any[]` | - |
151+
| loadingDelay | Set delay time for display loading to avoid flicker | `number` | - |
152+
| pollingInterval | Polling interval in milliseconds. After setting, it will enter polling mode and trigger `run` periodically. | `number` | - |
153+
| pollingSinceLastFinished | <ul><li> Whether start next polling request since last request finished. Default is `true`. </li><li> If set `false`, request will start every `pollingInterval` time. </li></ul> | `boolean` | true |
154+
| pollingWhenHidden | <ul><li> Whether to continue polling when the page is hidden. Default is `true`, that is, polling will not stop </li><li> If set to `false`, polling is temporarily stopped when the page is hidden, and the last polling is continued when the page is redisplayed </li></ul> | `boolean` | `true` |
155+
| debounceInterval | debounce interval, the unit is millisecond. After setting, request to enter debounce mode. | `number` | - |
156+
| loadingWhenDebounceStart | Whether set loading to `true` when the `run` function starts to execute. | `boolean` | `true` |
157+
| throttleInterval | throttle interval, the unit is millisecond. After setting, request to enter throttle mode. | `number` | - |
158+
| throwOnError | If the service errors, the error will only be logged. If you want an error to be thrown, pass the throwOnError: true | `boolean` | `false` |
159+
| refreshOnWindowFocus `v0.9` | The request will be re-initiated when the screen is refocused or revisible. | `boolean` | `false` |
160+
| refreshDeps `v0.9` | RefreshDeps changes will trigger the service to re-execute. | `WatchSource[]` | `[]` |
161+
| ready `v0.12.4` | Is the current request ready | `Ref<Boolean>` | `ref(true)` |

src/useRequest/index.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export function useRequest<R = any, P extends any[] = any>(
4646
pollingSinceLastFinished,
4747
refreshOnWindowFocus,
4848
refreshDeps,
49+
ready,
4950
} = finalOptions;
5051

5152
let promiseService: (...args: P) => Promise<any>;
@@ -99,6 +100,10 @@ export function useRequest<R = any, P extends any[] = any>(
99100
let pollingSinceFinishedTimer: any;
100101

101102
function _run(...args: P) {
103+
// 只要 ready=false 不执行
104+
if (!ready.value) {
105+
return Promise.resolve();
106+
}
102107
if (pollingSinceFinishedTimer) {
103108
clearTimeout(pollingSinceFinishedTimer);
104109
}
@@ -118,11 +123,11 @@ export function useRequest<R = any, P extends any[] = any>(
118123
params.value = cloneDeep(args);
119124

120125
// 抛弃该次请求结果
121-
const shoundAbandon = () => unmountedFlag || curCount !== count;
126+
const shouldAbandon = () => unmountedFlag || curCount !== count;
122127

123128
return promiseService(...args)
124129
.then(res => {
125-
if (shoundAbandon()) {
130+
if (shouldAbandon()) {
126131
return;
127132
}
128133
const formattedResult = formatResult(res);
@@ -133,7 +138,7 @@ export function useRequest<R = any, P extends any[] = any>(
133138
return formattedResult;
134139
})
135140
.catch(err => {
136-
if (shoundAbandon()) {
141+
if (shouldAbandon()) {
137142
return;
138143
}
139144
console.error(err);
@@ -144,7 +149,7 @@ export function useRequest<R = any, P extends any[] = any>(
144149
}
145150
})
146151
.finally(() => {
147-
if (shoundAbandon()) {
152+
if (shouldAbandon()) {
148153
return;
149154
}
150155
if (loadingDelayTimer) {
@@ -228,7 +233,18 @@ export function useRequest<R = any, P extends any[] = any>(
228233

229234
// 自动执行
230235
if (!manual) {
231-
run(...(defaultParams as P));
236+
// ready 变为true 自动发起请求,会带上参数 options.defaultParams
237+
watch(
238+
ready,
239+
() => {
240+
if (ready.value) {
241+
run(...(defaultParams as P));
242+
}
243+
},
244+
{
245+
immediate: true,
246+
},
247+
);
232248
}
233249

234250
// refreshDeps

0 commit comments

Comments
 (0)