Skip to content

Commit

Permalink
refactor(useRetryFn): rewrite using useVersionedAction
Browse files Browse the repository at this point in the history
  • Loading branch information
vikiboss committed Aug 15, 2024
1 parent 72adce9 commit 37ea224
Showing 1 changed file with 30 additions and 38 deletions.
68 changes: 30 additions & 38 deletions src/use-retry-fn/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useRef } from 'react'
import { useCreation } from '../use-creation'
import { useLatest } from '../use-latest'
import { useStableFn } from '../use-stable-fn'
import { useVersionedAction } from '../use-versioned-action'
import { isFunction, wait } from '../utils/basic'

import type { AnyFunc } from '../utils/basic'
Expand Down Expand Up @@ -67,7 +67,7 @@ export function defaultRetryInterval(currentCount: number) {
export function useRetryFn<T extends AnyFunc, E = any>(fn: T, options: UseRetryFnOptions<E> = {}): T {
const { count = 3, interval = defaultRetryInterval, onError, onErrorRetry, onRetryFailed } = options

const version = useRef(0)
const [incVersion, runVersionedAction] = useVersionedAction()

const latest = useLatest({
fn,
Expand All @@ -78,56 +78,48 @@ export function useRetryFn<T extends AnyFunc, E = any>(fn: T, options: UseRetryF
onRetryFailed,
})

const runFnWithRetry = useCreation(() => {
const retryFn = async (
retryState: UseRetryFnRetryState,
...args: Parameters<T>
): Promise<Awaited<ReturnType<T>> | undefined> => {
try {
const result = await latest.current.fn(...args)
const runFnWithRetry = useCreation(
() =>
async (retryState: UseRetryFnRetryState, ...args: Parameters<T>): Promise<Awaited<ReturnType<T>> | undefined> => {
try {
const result = await latest.current.fn(...args)

if (retryState.version !== version.current) {
return result
}

retryState.currentCount = 0

return result
} catch (error) {
if (retryState.version !== version.current) {
return
}

retryState.currentCount++
runVersionedAction(retryState.version, () => {
retryState.currentCount = 0
})

const { onError, onErrorRetry, onRetryFailed, interval } = latest.current
return result
} catch (error) {
return runVersionedAction(retryState.version, async () => {
retryState.currentCount++

onError?.(error as E | undefined)
const { onError, onErrorRetry, onRetryFailed, interval } = latest.current

if (retryState.currentCount > retryState.retryCount) {
onRetryFailed?.(error as E | undefined, { ...retryState })
retryState.currentCount = 0
return
}
onError?.(error as E | undefined)

const nextInterval = isFunction(interval) ? interval(retryState.currentCount) : interval
if (retryState.currentCount > retryState.retryCount) {
onRetryFailed?.(error as E | undefined, { ...retryState })
retryState.currentCount = 0
return
}

await wait(nextInterval)
const nextInterval = isFunction(interval) ? interval(retryState.currentCount) : interval

onErrorRetry?.(error as E | undefined, { ...retryState })
await wait(nextInterval)

return retryFn(retryState, ...args)
}
}
onErrorRetry?.(error as E | undefined, { ...retryState })

return retryFn
})
return runFnWithRetry({ ...retryState }, ...args)
})
}
},
)

const fnWithRetry = useStableFn(((...args: Parameters<T>) => {
const retryState = {
currentCount: 0,
retryCount: latest.current.count,
version: ++version.current,
version: incVersion(),
}

return runFnWithRetry(retryState, ...args)
Expand Down

0 comments on commit 37ea224

Please sign in to comment.