An open API service indexing awesome lists of open source software.

https://github.com/matthewbub/fetch-with-retry

A promise-based fetch with retry, heavily based on p-retry and is-network-error. This is a consolidated version of the two packages with type checking and a few other changes.
https://github.com/matthewbub/fetch-with-retry

Last synced: 11 months ago
JSON representation

A promise-based fetch with retry, heavily based on p-retry and is-network-error. This is a consolidated version of the two packages with type checking and a few other changes.

Awesome Lists containing this project

README

          

# fetch-with-retry

A promise-based fetch with retry, heavily based on [p-retry](https://github.com/sindresorhus/p-retry) and i[s-network-error](https://github.com/sindresorhus/is-network-error). This is a consolidated version of the two packages with type checking and a few other changes.

## Features

- **Exponential backoff** with configurable factor and randomization
- **Network error detection** across different browsers and environments
- **Abort signal support** for cancelling retry operations
- **Time-based limits** with `maxRetryTime` option
- **Custom retry logic** with `shouldRetry` callback
- **TypeScript support** with full type definitions
- **Zero dependencies** - consolidated implementation

## Usage

### Basic Example

```typescript
import { fetchWithRetry } from "./fetch-with-retry";

const result = await fetchWithRetry(
async (attemptNumber) => {
console.log(`Attempt ${attemptNumber}`);
return fetch("https://api.example.com/data");
},
{
retries: 3,
minTimeout: 1000,
maxTimeout: 5000,
factor: 2,
}
);
```

### Advanced Configuration

```typescript
import { fetchWithRetry } from "./fetch-with-retry";

const result = await fetchWithRetry(
async (attemptNumber) => {
const response = await fetch("https://api.example.com/data");
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return response.json();
},
{
retries: 5,
factor: 2,
minTimeout: 1000,
maxTimeout: 30000,
randomize: true,
maxRetryTime: 60000, // Stop after 1 minute total
onFailedAttempt: async ({ error, attemptNumber, retriesLeft }) => {
console.log(`Attempt ${attemptNumber} failed: ${error.message}`);
console.log(`${retriesLeft} retries left`);
},
shouldRetry: async ({ error, attemptNumber }) => {
// Don't retry on 4xx errors (client errors)
if (error.message.includes("HTTP 4")) {
return false;
}
return true;
},
signal: AbortSignal.timeout(120000), // Overall timeout
unref: true, // Don't keep Node.js process alive
}
);
```

## API

### `fetchWithRetry(input, options)`

#### Parameters

- **`input`** `(attemptNumber: number) => Promise` - Function that returns a promise to retry
- **`options`** `RetryOptions` - Configuration options

#### RetryOptions

| Option | Type | Default | Description |
| ----------------- | ------------- | ----------------------------- | --------------------------------------- |
| `retries` | `number` | `10` | Number of retry attempts |
| `factor` | `number` | `2` | Exponential backoff factor |
| `minTimeout` | `number` | `1000` | Minimum delay between retries (ms) |
| `maxTimeout` | `number` | `Infinity` | Maximum delay between retries (ms) |
| `randomize` | `boolean` | `false` | Add randomization to delays (1.0-2.0x) |
| `maxRetryTime` | `number` | `Infinity` | Maximum total time for all retries (ms) |
| `onFailedAttempt` | `function` | `() => Promise.resolve()` | Callback on each failed attempt |
| `shouldRetry` | `function` | `() => Promise.resolve(true)` | Custom retry logic |
| `signal` | `AbortSignal` | `undefined` | Abort signal for cancellation |
| `unref` | `boolean` | `false` | Don't keep Node.js process alive |

#### Callback Context

Both `onFailedAttempt` and `shouldRetry` receive a context object:

```typescript
{
error: Error; // The error that occurred
attemptNumber: number; // Current attempt (1-based)
retriesLeft: number; // Remaining retry attempts
}
```

## Development

### Scripts

- `pnpm run test` - Run tests with Vitest
- `pnpm run build` - Build TypeScript to JavaScript

### Testing

The project uses Vitest for testing. Tests cover network error detection across different browser environments and error conditions.

```bash
pnpm test
```

## License

MIT