Skip to content

Commit

Permalink
feat(useTimeoutPoll): new function (#1178)
Browse files Browse the repository at this point in the history
Co-authored-by: wangwenlu <wangwenlu@kuaishou.com>
  • Loading branch information
Kingwl and wangwenlu committed Mar 5, 2022
1 parent 5c445d8 commit abd59a2
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/core/index.ts
Expand Up @@ -96,6 +96,7 @@ export * from './useTemplateRefsList'
export * from './useTextSelection'
export * from './useThrottledRefHistory'
export * from './useTimeAgo'
export * from './useTimeoutPoll'
export * from './useTimestamp'
export * from './useTitle'
export * from './useTransition'
Expand Down
30 changes: 30 additions & 0 deletions packages/core/useTimeoutPoll/demo.vue
@@ -0,0 +1,30 @@
<script setup lang="ts">
import { ref } from 'vue-demi'
import { promiseTimeout } from '@vueuse/shared'
import { useTimeoutPoll } from '.'
const count = ref(0)
const fetchData = async() => {
await promiseTimeout(1000)
count.value++
}
const { isActive, pause, resume } = useTimeoutPoll(fetchData, 1000)
</script>

<template>
<div>
<div>Count: {{ count }}</div>
<div>isActive: {{ isActive }}</div>
<div>
<button @click="pause">
pause
</button>
<button @click="resume">
resume
</button>
</div>
</div>
</template>
23 changes: 23 additions & 0 deletions packages/core/useTimeoutPoll/index.md
@@ -0,0 +1,23 @@
---
category: Utilities
---

# useTimeoutPoll

Use timeout to poll something. It's will trigger callback after last task is done.

## Usage

```ts
import { useTimeoutPoll } from '@vueuse/core'

const count = ref(0)

const fetchData = async() => {
await promiseTimeout(1000)
count.value++
}

// Only trigger after last fetch is done
const { isActive, pause, resume } = useTimeoutPoll(fetchData, 1000)
```
39 changes: 39 additions & 0 deletions packages/core/useTimeoutPoll/index.test.ts
@@ -0,0 +1,39 @@
import { ref } from 'vue-demi'
import { promiseTimeout } from '@vueuse/shared'
import { useTimeoutPoll } from '.'

describe('useTimeoutFn', () => {
it('supports reactive intervals', async() => {
const callback = vitest.fn()
const interval = ref(0)
const { pause, resume } = useTimeoutPoll(callback, interval)

resume()
await promiseTimeout(1)
expect(callback).toBeCalled()
pause()

interval.value = 50

resume()
callback.mockReset()

await promiseTimeout(1)
expect(callback).not.toBeCalled()
await promiseTimeout(101)
expect(callback).toBeCalled()

callback.mockReset()
pause()
await promiseTimeout(101)
expect(callback).not.toBeCalled()

resume()
await promiseTimeout(1)
expect(callback).toBeCalled()

callback.mockReset()
await promiseTimeout(101)
expect(callback).toBeCalled()
})
})
39 changes: 39 additions & 0 deletions packages/core/useTimeoutPoll/index.ts
@@ -0,0 +1,39 @@
import { ref } from 'vue-demi'
import type { Awaitable, MaybeRef, Pausable, TimeoutFnOptions } from '@vueuse/shared'
import { tryOnScopeDispose, useTimeoutFn } from '@vueuse/shared'

export function useTimeoutPoll(fn: () => Awaitable<void>, interval: MaybeRef<number>, timeoutPollOptions?: TimeoutFnOptions): Pausable {
const { start } = useTimeoutFn(loop, interval)

const isActive = ref(false)

async function loop() {
if (!isActive.value)
return

await fn()
start()
}

function resume() {
if (!isActive.value) {
isActive.value = true
loop()
}
}

function pause() {
isActive.value = false
}

if (timeoutPollOptions?.immediate)
resume()

tryOnScopeDispose(pause)

return {
isActive,
pause,
resume,
}
}

0 comments on commit abd59a2

Please sign in to comment.