Convert Figma logo to code with AI

sindresorhus logop-retry

Retry a promise-returning or async function

1,009
79
1,009
1

Top Related Projects

Retrying made simple, easy and async

Abstraction for exponential and custom retry strategies for failed operations.

Axios plugin that intercepts failed requests and retries them whenever possible

Quick Overview

p-retry is a JavaScript library that provides retry functionality for promises. It allows you to automatically retry failed operations with customizable retry strategies, including exponential backoff. This library is particularly useful for handling network requests or other operations that may fail intermittently.

Pros

  • Easy to use and integrate into existing promise-based code
  • Supports customizable retry strategies, including exponential backoff
  • Provides TypeScript support for better type checking and IDE integration
  • Lightweight with no external dependencies

Cons

  • Limited to promise-based operations
  • May not be suitable for complex retry scenarios that require more advanced logic
  • Could potentially mask underlying issues if used incorrectly
  • Requires careful consideration of retry limits to avoid excessive retries

Code Examples

  1. Basic usage with default options:
import pRetry from 'p-retry';

const result = await pRetry(async () => {
    // Attempt some operation that might fail
    const response = await fetch('https://api.example.com/data');
    if (!response.ok) throw new Error('API request failed');
    return response.json();
});
  1. Custom retry options:
import pRetry from 'p-retry';

const result = await pRetry(
    async () => {
        // Attempt some operation that might fail
        const response = await fetch('https://api.example.com/data');
        if (!response.ok) throw new Error('API request failed');
        return response.json();
    },
    {
        retries: 5,
        onFailedAttempt: error => {
            console.log(`Attempt ${error.attemptNumber} failed. There are ${error.retriesLeft} retries left.`);
        }
    }
);
  1. Using with AbortController:
import pRetry from 'p-retry';

const abortController = new AbortController();

try {
    const result = await pRetry(
        async () => {
            const response = await fetch('https://api.example.com/data', {
                signal: abortController.signal
            });
            if (!response.ok) throw new Error('API request failed');
            return response.json();
        },
        { signal: abortController.signal }
    );
} catch (error) {
    if (error.name === 'AbortError') {
        console.log('Operation was aborted');
    } else {
        console.error('Operation failed after retries:', error);
    }
}

Getting Started

To use p-retry in your project, first install it using npm:

npm install p-retry

Then, import and use it in your JavaScript/TypeScript code:

import pRetry from 'p-retry';

async function fetchData() {
    return pRetry(async () => {
        const response = await fetch('https://api.example.com/data');
        if (!response.ok) throw new Error('API request failed');
        return response.json();
    }, { retries: 3 });
}

fetchData().then(data => console.log(data)).catch(error => console.error(error));

This example demonstrates how to use p-retry to fetch data from an API with up to 3 retry attempts.

Competitor Comparisons

Retrying made simple, easy and async

Pros of async-retry

  • Simpler API with fewer options, making it easier to use for basic retry scenarios
  • Built-in support for custom retry strategies through the retries option
  • Lightweight package with minimal dependencies

Cons of async-retry

  • Less flexible than p-retry in terms of customization options
  • Lacks built-in support for exponential backoff (though it can be implemented manually)
  • Does not provide as many advanced features, such as abort control or custom error handling

Code Comparison

p-retry:

import pRetry from 'p-retry';

await pRetry(async () => {
    // Attempt task here
}, { retries: 5 });

async-retry:

import retry from 'async-retry';

await retry(async (bail) => {
    // Attempt task here
}, { retries: 5 });

Both libraries offer similar basic functionality for retrying asynchronous operations. p-retry provides more advanced features and customization options, while async-retry offers a simpler API for basic retry scenarios. The choice between the two depends on the specific requirements of your project and the level of control you need over the retry process.

Abstraction for exponential and custom retry strategies for failed operations.

Pros of node-retry

  • More flexible retry strategies with customizable backoff algorithms
  • Supports both callback and promise-based approaches
  • Includes built-in timeout functionality

Cons of node-retry

  • Less actively maintained compared to p-retry
  • Lacks TypeScript support out of the box
  • More complex API, potentially steeper learning curve

Code Comparison

node-retry:

var retry = require('retry');
var operation = retry.operation({
  retries: 5,
  factor: 3,
  minTimeout: 1 * 1000,
  maxTimeout: 60 * 1000,
  randomize: true,
});

operation.attempt(function(currentAttempt) {
  // ... attempt operation
});

p-retry:

const pRetry = require('p-retry');

await pRetry(async () => {
  // ... attempt operation
}, {
  retries: 5
});

Both libraries provide retry functionality, but node-retry offers more granular control over retry behavior at the cost of a more verbose API. p-retry, on the other hand, provides a simpler, promise-based interface that integrates well with modern JavaScript practices.

While node-retry supports both callbacks and promises, p-retry is designed specifically for promise-based operations, making it more suitable for projects using async/await syntax. However, node-retry's flexibility in retry strategies and timeout handling can be advantageous in complex scenarios where fine-tuned control is necessary.

Axios plugin that intercepts failed requests and retries them whenever possible

Pros of axios-retry

  • Specifically designed for Axios, providing seamless integration
  • Offers more granular control over retry behavior for HTTP requests
  • Includes built-in exponential backoff strategy

Cons of axios-retry

  • Limited to Axios library, not as versatile for other use cases
  • Less customizable retry logic compared to p-retry
  • Smaller community and fewer updates

Code Comparison

p-retry:

import pRetry from 'p-retry';

await pRetry(() => fetchSomething(), { retries: 5 });

axios-retry:

import axios from 'axios';
import axiosRetry from 'axios-retry';

axiosRetry(axios, { retries: 3 });
axios.get('https://example.com');

Key Differences

  1. Scope: p-retry is a general-purpose retry utility, while axios-retry is specific to Axios HTTP requests.
  2. Configuration: axios-retry is configured globally for an Axios instance, whereas p-retry is applied to individual function calls.
  3. Flexibility: p-retry can wrap any asynchronous function, making it more versatile for various scenarios beyond HTTP requests.
  4. Error handling: p-retry provides more control over which errors trigger retries, while axios-retry focuses on HTTP-specific error conditions.
  5. Community: p-retry has a larger user base and more frequent updates, potentially offering better long-term support and maintenance.

Both libraries serve their purposes well, with p-retry offering more flexibility for general use cases and axios-retry providing a tailored solution for Axios users.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

p-retry

Retry a promise-returning or async function

It does exponential backoff and supports custom retry strategies for failed operations.

Install

npm install p-retry

Usage

import pRetry, {AbortError} from 'p-retry';
import fetch from 'node-fetch';

const run = async () => {
	const response = await fetch('https://sindresorhus.com/unicorn');

	// Abort retrying if the resource doesn't exist
	if (response.status === 404) {
		throw new AbortError(response.statusText);
	}

	return response.blob();
};

console.log(await pRetry(run, {retries: 5}));

API

pRetry(input, options?)

Returns a Promise that is fulfilled when calling input returns a fulfilled promise. If calling input returns a rejected promise, input is called again until the maximum number of retries is reached. It then rejects with the last rejection reason.

It does not retry on most TypeError's, with the exception of network errors. This is done on a best case basis as different browsers have different messages to indicate this. See whatwg/fetch#526 (comment)

input

Type: Function

Receives the current attempt number as the first argument and is expected to return a Promise or any value.

options

Type: object

Options are passed to the retry module.

onFailedAttempt(error)

Type: Function

Callback invoked on each retry. Receives the error thrown by input as the first argument with properties attemptNumber and retriesLeft which indicate the current attempt number and the number of attempts left, respectively.

import pRetry from 'p-retry';

const run = async () => {
	const response = await fetch('https://sindresorhus.com/unicorn');

	if (!response.ok) {
		throw new Error(response.statusText);
	}

	return response.json();
};

const result = await pRetry(run, {
	onFailedAttempt: error => {
		console.log(`Attempt ${error.attemptNumber} failed. There are ${error.retriesLeft} retries left.`);
		// 1st request => Attempt 1 failed. There are 4 retries left.
		// 2nd request => Attempt 2 failed. There are 3 retries left.
		// …
	},
	retries: 5
});

console.log(result);

The onFailedAttempt function can return a promise. For example, you can do some async logging:

import pRetry from 'p-retry';
import logger from './some-logger';

const run = async () => { … };

const result = await pRetry(run, {
	onFailedAttempt: async error => {
		await logger.log(error);
	}
});

If the onFailedAttempt function throws, all retries will be aborted and the original promise will reject with the thrown error.

shouldRetry(error)

Type: Function

Decide if a retry should occur based on the error. Returning true triggers a retry, false aborts with the error.

It is not called for TypeError (except network errors) and AbortError.

import pRetry from 'p-retry';

const run = async () => { … };

const result = await pRetry(run, {
	shouldRetry: error => !(error instanceof CustomError);
});

In the example above, the operation will be retried unless the error is an instance of CustomError.

signal

Type: AbortSignal

You can abort retrying using AbortController.

import pRetry from 'p-retry';

const run = async () => { … };
const controller = new AbortController();

cancelButton.addEventListener('click', () => {
	controller.abort(new Error('User clicked cancel button'));
});

try {
	await pRetry(run, {signal: controller.signal});
} catch (error) {
	console.log(error.message);
	//=> 'User clicked cancel button'
}

AbortError(message)

AbortError(error)

Abort retrying and reject the promise.

message

Type: string

An error message.

error

Type: Error

A custom error.

Tip

You can pass arguments to the function being retried by wrapping it in an inline arrow function:

import pRetry from 'p-retry';

const run = async emoji => {
	// …
};

// Without arguments
await pRetry(run, {retries: 5});

// With arguments
await pRetry(() => run('🦄'), {retries: 5});

Related

NPM DownloadsLast 30 Days