From cfadd0c91ea4b60c06bfcc84acddcedd22623be4 Mon Sep 17 00:00:00 2001 From: fh Date: Fri, 3 Jan 2025 15:16:33 +0800 Subject: [PATCH] feat(retry): add retry --- docs/ja/reference/function/retry.md | 45 ++++++++++++++ docs/ko/reference/function/retry.md | 45 ++++++++++++++ docs/reference/function/retry.md | 45 ++++++++++++++ docs/zh_hans/reference/function/retry.md | 45 ++++++++++++++ src/function/index.ts | 1 + src/function/retry.spec.ts | 25 ++++++++ src/function/retry.ts | 77 ++++++++++++++++++++++++ 7 files changed, 283 insertions(+) create mode 100644 docs/ja/reference/function/retry.md create mode 100644 docs/ko/reference/function/retry.md create mode 100644 docs/reference/function/retry.md create mode 100644 docs/zh_hans/reference/function/retry.md create mode 100644 src/function/retry.spec.ts create mode 100644 src/function/retry.ts diff --git a/docs/ja/reference/function/retry.md b/docs/ja/reference/function/retry.md new file mode 100644 index 000000000..f6273e239 --- /dev/null +++ b/docs/ja/reference/function/retry.md @@ -0,0 +1,45 @@ +# retry + +この関数は再試行間隔と再試行回数を設定し、再試行の最大回数に達するとエラーをスローします。 + +## インターフェース + +```typescript +function retry(func: () => Promise, options: RetryOptions): T; +``` + +### パラメータ + +- `func` (`F`): 再試行する関数。 +- `options` (`RetryOptions`): オプション オブジェクト。 + - `intervalMs`: 間隔遅延のミリ秒数。 + - `retries`: 再試行の回数。 + +### 戻り値 + +(`Awaited>`): 関数の戻り値 + +### Error + +再試行回数が `retries` に達するとエラーが発生します + +## 例 + +```typescript +async function getNumber() { + return Promise.resolve(3); +} +async function getError() { + return Promise.reject(new Error('MyFailed')); +} +// 結果は3になります +await retry(getNumber, { + intervalMs: 1000, + retries: 2, +}); +// 2回実行すると例外がスローされます +await retry(getError, { + intervalMs: 1000, + retries: 2, +}); +``` diff --git a/docs/ko/reference/function/retry.md b/docs/ko/reference/function/retry.md new file mode 100644 index 000000000..b9018c658 --- /dev/null +++ b/docs/ko/reference/function/retry.md @@ -0,0 +1,45 @@ +# retry + +이 기능은 재시도 간격과 재시도 횟수를 설정하고, 최대 재시도 횟수에 도달하면 오류를 발생시킵니다. + +## 인터페이스 + +```typescript +function retry(func: () => Promise, options: RetryOptions): T; +``` + +### 파라미터 + +- `func` (`F`): 다시 시도하는 기능입니다. +- `options` (`RetryOptions`): 옵션 객체. + - `intervalMs`: 간격 지연의 밀리초 수입니다. + - `retries`: 재시도 횟수입니다. + +### 반환 값 + +(`Awaited>`): 함수 반환 값. + +### Error + +재시도 횟수가 `retries`에 도달하면 오류가 발생합니다. + +## 예시 + +```typescript +async function getNumber() { + return Promise.resolve(3); +} +async function getError() { + return Promise.reject(new Error('MyFailed')); +} +// 결과는 3이 됩니다 +await retry(getNumber, { + intervalMs: 1000, + retries: 2, +}); +// 2번 실행 후 예외가 발생합니다. +await retry(getError, { + intervalMs: 1000, + retries: 2, +}); +``` diff --git a/docs/reference/function/retry.md b/docs/reference/function/retry.md new file mode 100644 index 000000000..082ae3f64 --- /dev/null +++ b/docs/reference/function/retry.md @@ -0,0 +1,45 @@ +# retry + +This function can set the retry interval and the number of retries, and throw an Error after the maximum number of retries is reached. + +## Signature + +```typescript +function retry(func: () => Promise, options: RetryOptions): T; +``` + +### Parameters + +- `func` (`F`): The function to retry. +- `options` (`RetryOptions`): An options object. + - `intervalMs`: The number of milliseconds to interval delay. + - `retries`: The number of retries to attemptcalled. + +### Returns + +(`Awaited>`): Function return value + +### Error + +Throws an error if the number of retries reaches `retries` + +## Examples + +```typescript +async function getNumber() { + return Promise.resolve(3); +} +async function getError() { + return Promise.reject(new Error('MyFailed')); +} +// The result will be 3 +await retry(getNumber, { + intervalMs: 1000, + retries: 2, +}); +// After executing twice, an exception is thrown +await retry(getError, { + intervalMs: 1000, + retries: 2, +}); +``` diff --git a/docs/zh_hans/reference/function/retry.md b/docs/zh_hans/reference/function/retry.md new file mode 100644 index 000000000..216ae69ff --- /dev/null +++ b/docs/zh_hans/reference/function/retry.md @@ -0,0 +1,45 @@ +# retry + +该函数可以设置重试间隔以及重试次数,达到最大重试次数后抛出Error。 + +## 签名 + +```typescript +function retry(func: () => Promise, options: RetryOptions): T; +``` + +### 参数 + +- `func` (`F`): 重试的功能函数 +- `options` (`RetryOptions`): 选项 + - `intervalMs`: 间隔延迟的毫秒数. + - `retries`: 最大重试次数. + +### 返回值 + +(`Awaited>`): 函数返回值 + +### 异常 + +如果重试次数达到 `retries` 则抛出错误 + +## 示例 + +```typescript +async function getNumber() { + return Promise.resolve(3); +} +async function getError() { + return Promise.reject(new Error('MyFailed')); +} +// 将返回 3 +await retry(getNumber, { + intervalMs: 1000, + retries: 2, +}); +// 将抛出异常 +await retry(getError, { + intervalMs: 1000, + retries: 2, +}); +``` diff --git a/src/function/index.ts b/src/function/index.ts index e3ab8311c..219a3d2ee 100644 --- a/src/function/index.ts +++ b/src/function/index.ts @@ -15,6 +15,7 @@ export { once } from './once.ts'; export { partial } from './partial.ts'; export { partialRight } from './partialRight.ts'; export { rest } from './rest.ts'; +export { retry } from './retry.ts'; export { spread } from './spread.ts'; export { throttle, type ThrottledFunction } from './throttle.ts'; export { unary } from './unary.ts'; diff --git a/src/function/retry.spec.ts b/src/function/retry.spec.ts new file mode 100644 index 000000000..81af90039 --- /dev/null +++ b/src/function/retry.spec.ts @@ -0,0 +1,25 @@ +import { describe, expect, it } from 'vitest'; +import { retry } from './retry'; + +async function getNumber() { + return Promise.resolve(3); +} + +async function getError() { + return Promise.reject(new Error('MyFailed')); +} + +// Tests +describe('retry', () => { + it('Execute successfully and return value', async () => { + const num = await retry(getNumber, { intervalMs: 1000, retries: 3 }); + expect(num).toBe(3); + }); + it('Retry multiple times and throw an exception', async () => { + expect(retry(getError, { intervalMs: 1000, retries: 2 })).rejects.toThrowError(new Error('MyFailed')); + }); + + it('When retries is 0, a fallback error is triggered', async () => { + expect(retry(getError, { intervalMs: 1000, retries: 0 })).rejects.toThrowError(new Error('Failed after maximum retries')); + }); +}); diff --git a/src/function/retry.ts b/src/function/retry.ts new file mode 100644 index 000000000..b384e58eb --- /dev/null +++ b/src/function/retry.ts @@ -0,0 +1,77 @@ +import { delay } from '../promise'; + +interface RetryOptions { + /** + * The number of milliseconds to interval delay. + */ + intervalMs: number; + + /** + * The number of retries to attempt + */ + retries: number; +} +/** + * Function for asynchronous retry + * + * This function can set the retry interval and the number of retries, and throw an Error after the maximum number of retries is reached. + * + * @template F - The type of the function to be invoked. + * @param {F} func - The function to be invoked. + * @param {RetryOptions} options - The options object + * @returns {Awaited>} - Function return value + * @throws {Error} - Throws an error if the maximum number of retries is exceeded. + * @example + * + * async function getNumber() { + * return Promise.resolve(3); + * } + * async function getError() { + * return Promise.reject(new Error('MyFailed')); + * } + * // The result will be 3 + * await retry(getNumber, { + * intervalMs: 1000, + * retries: 2, + * }); + * // After executing twice, an exception is thrown + * await retry(getError, { + * intervalMs: 1000, + * retries: 2, + * }); + */ + +export async function retry(func: () => Promise, options: RetryOptions): Promise { + const { intervalMs, retries } = options; + + for (let i = 0; i < retries; i++) { + try { + return await func(); + } catch (error) { + if (i === retries - 1) { + throw error; + } + await delay(intervalMs); + } + } + throw new Error('Failed after maximum retries'); +} + +/* async function getNumber() { + return Promise.resolve(3); +} +async function getError() { + return Promise.reject(new Error('MyFailed')); +} +// The result will be 3 +await retry(getNumber, { + intervalMs: 1000, + retries: 2, +}); +// After executing twice, an exception is thrown +await retry(getError, { + intervalMs: 1000, + retries: 2, +}); + + */