Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions docs/ja/reference/function/retry.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,22 @@ const data4 = await retry(
delay: attempts => Math.min(100 * Math.pow(2, attempts), 5000),
}
);

// エラーに基づく再試行間隔 (例: Retry-After ヘッダー)
const data5 = await retry(
async () => {
return await fetchData();
},
{
retries: 3,
delay: (_attempts, error) => {
if ((error as { status?: number }).status === 429) {
return (error as { retryAfter: number }).retryAfter * 1000;
}
return 1000;
},
}
);
```

特定のエラーでのみ再試行したい場合は `shouldRetry` オプションを使用できます。
Expand All @@ -64,7 +80,7 @@ class NetworkError extends Error {
}

// 500エラー以上でのみ再試行
const data5 = await retry(
const data6 = await retry(
async () => {
const response = await fetch('/api/data');
if (!response.ok) {
Expand Down Expand Up @@ -111,7 +127,7 @@ try {
- `func` (`() => Promise<T>`): 再試行する非同期関数です。
- `options` (`number | RetryOptions`, オプション): 再試行回数またはオプションオブジェクトです。
- `retries` (`number`, オプション): 再試行する回数です。デフォルトは `Infinity` で無限に再試行します。
- `delay` (`number | (attempts: number) => number`, オプション): 再試行間隔(ミリ秒)です。数値または関数を使用できます。デフォルトは `0` です。
- `delay` (`number | (attempts: number, error: unknown) => number`, オプション): 再試行間隔(ミリ秒)です。数値または関数を使用できます。関数は試行回数とエラーオブジェクトを受け取ります。デフォルトは `0` です。
- `signal` (`AbortSignal`, オプション): 再試行をキャンセルできるシグナルです。
- `shouldRetry` (`(error: unknown, attempt: number) => boolean`, オプション): 再試行するかどうかを決定する関数です。`false` を返すと即座にエラーをスローします。
- `error`: 発生したエラーオブジェクトです。
Expand Down
20 changes: 18 additions & 2 deletions docs/ko/reference/function/retry.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,22 @@ const data4 = await retry(
delay: attempts => Math.min(100 * Math.pow(2, attempts), 5000),
}
);

// 에러 기반 재시도 간격 (예: Retry-After 헤더 활용)
const data5 = await retry(
async () => {
return await fetchData();
},
{
retries: 3,
delay: (_attempts, error) => {
if ((error as { status?: number }).status === 429) {
return (error as { retryAfter: number }).retryAfter * 1000;
}
return 1000;
},
}
);
```

특정 에러에서만 재시도하고 싶을 때 `shouldRetry` 옵션을 사용할 수 있어요.
Expand All @@ -64,7 +80,7 @@ class NetworkError extends Error {
}

// 500 에러 이상에서만 재시도
const data5 = await retry(
const data6 = await retry(
async () => {
const response = await fetch('/api/data');
if (!response.ok) {
Expand Down Expand Up @@ -111,7 +127,7 @@ try {
- `func` (`() => Promise<T>`): 재시도할 비동기 함수예요.
- `options` (`number | RetryOptions`, 선택): 재시도 횟수나 옵션 객체예요.
- `retries` (`number`, 선택): 재시도할 횟수예요. 기본값은 `Infinity`로 무한 재시도해요.
- `delay` (`number | (attempts: number) => number`, 선택): 재시도 간격(밀리초)이에요. 숫자나 함수를 사용할 수 있어요. 기본값은 `0`이에요.
- `delay` (`number | (attempts: number, error: unknown) => number`, 선택): 재시도 간격(밀리초)이에요. 숫자나 함수를 사용할 수 있어요. 함수는 시도 횟수와 에러 객체를 인자로 받아요. 기본값은 `0`이에요.
- `signal` (`AbortSignal`, 선택): 재시도를 취소할 수 있는 시그널이에요.
- `shouldRetry` (`(error: unknown, attempt: number) => boolean`, 선택): 재시도 여부를 결정하는 함수예요. `false`를 반환하면 즉시 에러를 던져요.
- `error`: 발생한 에러 객체예요.
Expand Down
20 changes: 18 additions & 2 deletions docs/reference/function/retry.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,22 @@ const data4 = await retry(
delay: attempts => Math.min(100 * Math.pow(2, attempts), 5000),
}
);

// Error-based retry interval (e.g., respect Retry-After headers)
const data5 = await retry(
async () => {
return await fetchData();
},
{
retries: 3,
delay: (_attempts, error) => {
if ((error as { status?: number }).status === 429) {
return (error as { retryAfter: number }).retryAfter * 1000;
}
Comment on lines +61 to +64
return 1000;
},
}
);
```

You can use `shouldRetry` option when you want to retry only on specific errors.
Expand All @@ -64,7 +80,7 @@ class NetworkError extends Error {
}

// Retry only on 500+ errors
const data5 = await retry(
const data6 = await retry(
async () => {
const response = await fetch('/api/data');
if (!response.ok) {
Expand Down Expand Up @@ -111,7 +127,7 @@ try {
- `func` (`() => Promise<T>`): The asynchronous function to retry.
- `options` (`number | RetryOptions`, optional): The number of retries or options object.
- `retries` (`number`, optional): The number of times to retry. Defaults to `Infinity` for infinite retries.
- `delay` (`number | (attempts: number) => number`, optional): The retry interval (in milliseconds). Can be a number or a function. Defaults to `0`.
- `delay` (`number | (attempts: number, error: unknown) => number`, optional): The retry interval (in milliseconds). Can be a number or a function. The function receives the attempt number and the error object. Defaults to `0`.
- `signal` (`AbortSignal`, optional): A signal that can cancel retries.
- `shouldRetry` (`(error: unknown, attempt: number) => boolean`, optional): A function that determines whether to retry. If it returns `false`, the error is thrown immediately.
- `error`: The error object that occurred.
Expand Down
20 changes: 18 additions & 2 deletions docs/zh_hans/reference/function/retry.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,22 @@ const data4 = await retry(
delay: attempts => Math.min(100 * Math.pow(2, attempts), 5000),
}
);

// 基于错误的重试间隔 (如: 使用 Retry-After 响应头)
const data5 = await retry(
async () => {
return await fetchData();
},
{
retries: 3,
delay: (_attempts, error) => {
if ((error as { status?: number }).status === 429) {
return (error as { retryAfter: number }).retryAfter * 1000;
}
return 1000;
},
}
);
```

当只想在特定错误时重试时,可以使用 `shouldRetry` 选项。
Expand All @@ -64,7 +80,7 @@ class NetworkError extends Error {
}

// 仅在 500+ 错误时重试
const data5 = await retry(
const data6 = await retry(
async () => {
const response = await fetch('/api/data');
if (!response.ok) {
Expand Down Expand Up @@ -111,7 +127,7 @@ try {
- `func` (`() => Promise<T>`): 要重试的异步函数。
- `options` (`number | RetryOptions`, 可选): 重试次数或选项对象。
- `retries` (`number`, 可选): 重试次数。默认值为 `Infinity`,无限重试。
- `delay` (`number | (attempts: number) => number`, 可选): 重试间隔(毫秒)。可以使用数字或函数。默认值为 `0`。
- `delay` (`number | (attempts: number, error: unknown) => number`, 可选): 重试间隔(毫秒)。可以使用数字或函数。函数接收尝试次数和错误对象。默认值为 `0`。
- `signal` (`AbortSignal`, 可选): 可以取消重试的信号。
- `shouldRetry` (`(error: unknown, attempt: number) => boolean`, 可选): 决定是否重试的函数。如果返回 `false`,则立即抛出错误。
- `error`: 发生的错误对象。
Expand Down
10 changes: 10 additions & 0 deletions src/function/retry.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,16 @@ describe('retry', () => {
expect(shouldRetry).toHaveBeenCalledWith(error, 0);
});

it('should pass error to delay function', async () => {
const error = new Error('Server Error');
const func = vi.fn().mockRejectedValueOnce(error).mockResolvedValue('success');
const delayFn = vi.fn(() => 0);

await retry(func, { delay: delayFn, retries: 1 });

expect(delayFn).toHaveBeenCalledWith(0, error);
});

it('should pass attempt number to shouldRetry', async () => {
const error = new Error('failure');
const func = vi.fn().mockRejectedValue(error);
Expand Down
15 changes: 9 additions & 6 deletions src/function/retry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ interface RetryOptions {
*
* @default 0
* @example
* delay: (attempts) => attempt * 50
* delay: (attempts, error) => error.status === 429 ? 10000 : attempts * 50
*/
delay?: number | ((attempts: number) => number);
delay?: number | ((attempts: number, error: unknown) => number);

/**
* The number of retries to attempt.
Expand Down Expand Up @@ -73,7 +73,7 @@ export async function retry<T>(func: () => Promise<T>, retries: number): Promise
* @template T
* @param func - The function to retry. It should return a promise.
* @param options - Options to configure the retry behavior.
* @param [options.delay=0] - Delay(milliseconds) between retries.
* @param [options.delay=0] - Delay(milliseconds) between retries. A number or a function that receives the attempt number and the error object.
* @param [options.retries=Infinity] - The number of retries to attempt.
* @param [options.signal] - An AbortSignal to cancel the retry operation.
* @param [options.shouldRetry] - A function that determines whether to retry.
Expand All @@ -88,7 +88,10 @@ export async function retry<T>(func: () => Promise<T>, retries: number): Promise
* retry(() => fetchData(), { delay: 1000, retries: 5 });
*
* // Retry a function with a delay increasing linearly by 50ms per attempt
* retry(() => fetchData(), { delay: (attempts) => attempt * 50, retries: 5 });
* retry(() => fetchData(), { delay: (attempts) => attempts * 50, retries: 5 });
*
* // Retry a function with an error-aware delay (e.g., respect Retry-After headers)
* retry(() => fetchData(), { delay: (_attempts, error) => error.status === 429 ? 10000 : 1000, retries: 3 });
*
* @example
* // Retry a function with exponential backoff + jitter (max delay 10 seconds)
Expand All @@ -108,7 +111,7 @@ export async function retry<T>(func: () => Promise<T>, options: RetryOptions): P
* @returns A promise that resolves with the value of the successful function call.
*/
export async function retry<T>(func: () => Promise<T>, _options?: number | RetryOptions): Promise<T> {
let delay: number | ((attempts: number) => number);
let delay: number | ((attempts: number, error: unknown) => number);
let retries: number;
let signal: AbortSignal | undefined;
let shouldRetry: (error: unknown, attempt: number) => boolean;
Expand Down Expand Up @@ -142,7 +145,7 @@ export async function retry<T>(func: () => Promise<T>, _options?: number | Retry
throw err;
}

const currentDelay = typeof delay === 'function' ? delay(attempts) : delay;
const currentDelay = typeof delay === 'function' ? delay(attempts, error) : delay;
await delayToolkit(currentDelay);
Comment on lines 145 to 149
}
}
Expand Down