retry vs p-retry vs promise-retry vs async-retry vs retry-axios
JavaScript Retry Libraries Comparison
3 Years
retryp-retrypromise-retryasync-retryretry-axiosSimilar Packages:
What's JavaScript Retry Libraries?

JavaScript Retry Libraries are tools that help developers automatically retry failed asynchronous operations, such as network requests or database queries. These libraries implement retry logic, allowing the application to attempt the operation again after a failure, which can be useful for handling transient errors (temporary issues that may resolve on their own). By using a retry library, developers can improve the resilience and reliability of their applications, reducing the impact of temporary failures on user experience. Each library may offer different features, such as customizable retry intervals, exponential backoff strategies, and support for promises or callbacks. Some libraries are lightweight and focused on simplicity, while others provide more advanced configurations and integrations. Overall, these libraries help automate the process of retrying failed operations, making it easier for developers to handle errors gracefully and improve the robustness of their applications.

Package Weekly Downloads Trend
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
retry44,108,226
1,258-194 years agoMIT
p-retry17,334,857
90213.2 kB59 months agoMIT
promise-retry16,409,109
318-115 years agoMIT
async-retry10,851,647
1,887-304 years agoMIT
retry-axios1,038,419
49936.4 kB392 years agoApache-2.0
Feature Comparison: retry vs p-retry vs promise-retry vs async-retry vs retry-axios

Retry Logic

  • retry:

    retry is a feature-rich library that supports retrying both asynchronous and synchronous operations. It offers advanced configuration options, including exponential backoff, custom retry strategies, and event hooks for monitoring the retry process. This makes it suitable for complex use cases where fine-grained control over the retry logic is required.

  • p-retry:

    p-retry focuses on retrying a single promise-returning function with a simple and intuitive API. You can specify the number of retries and provide a function to determine the delay between retries. It is lightweight and easy to use, making it ideal for straightforward retry scenarios.

  • promise-retry:

    promise-retry allows you to retry a promise-based operation with customizable retry logic. You can define the number of retries, delay between retries, and use a backoff function to control the delay. It provides a clear and simple interface for retrying failed promises, making it easy to integrate into your code.

  • async-retry:

    async-retry provides flexible retry logic for asynchronous functions, allowing you to specify the number of retries, delay between retries, and customize the retry behavior using a callback function. It supports exponential backoff by default, making it suitable for handling transient errors in a variety of scenarios.

  • retry-axios:

    retry-axios extends Axios to automatically retry failed HTTP requests. It integrates seamlessly with Axios and allows you to configure retry logic, including the number of retries, delay between retries, and conditions for retrying. This library is particularly useful for handling transient network errors in API calls.

Integration with Promises

  • retry:

    retry supports both asynchronous and synchronous operations, giving you the flexibility to retry a wide range of functions. It can handle promise-based functions as well as traditional callback-based or synchronous functions, making it a versatile choice for various use cases.

  • p-retry:

    p-retry is designed specifically for promise-based functions, making it a natural fit for retrying operations that return promises. Its API is built around the concept of handling promise rejections, which makes it intuitive for developers familiar with asynchronous programming.

  • promise-retry:

    promise-retry is focused on retrying promise-returning functions, providing a clear and straightforward way to handle promise rejections and implement retry logic. It is well-suited for scenarios where you need to retry a specific promise-based operation multiple times.

  • async-retry:

    async-retry works seamlessly with asynchronous functions, including those that return promises. It can be easily integrated into any async function, making it versatile and compatible with modern JavaScript code.

  • retry-axios:

    retry-axios is specifically designed for use with Axios, a popular HTTP client for making API requests. It integrates directly with Axios instances and interceptors, allowing you to automatically retry failed HTTP requests without modifying your existing code.

Customization

  • retry:

    retry is highly customizable, with extensive options for configuring the retry process. You can set the number of retries, define custom backoff strategies, implement your own retry conditions, and use event hooks to monitor the retry process. This makes it a powerful choice for applications that require detailed control over how retries are handled.

  • p-retry:

    p-retry provides basic customization options, such as setting the number of retries and defining a delay function. However, it is designed to be simple and lightweight, so it does not offer as much configurability as some other libraries. This makes it easy to use but may limit flexibility for more complex scenarios.

  • promise-retry:

    promise-retry offers good customization capabilities, allowing you to specify the number of retries, delay between retries, and a custom backoff function. You can also provide a function to determine whether to retry based on the error, giving you control over the retry logic while keeping the API straightforward.

  • async-retry:

    async-retry allows for significant customization of the retry logic, including the number of retries, delay between retries, and the ability to provide a custom retry condition. You can also implement your own backoff strategy by providing a function to calculate the delay between retries, giving you flexibility in how retries are handled.

  • retry-axios:

    retry-axios allows customization of the retry logic for HTTP requests, including setting the number of retries, delay between retries, and conditions for retrying based on the response status or error. It provides a configuration object that can be passed to the Axios instance, making it easy to adjust the retry behavior as needed.

Code Example

  • retry:

    Example of retry:

    const retry = require('retry');
    
    function unreliableFunction() {
      // Simulate a function that may fail
      return new Promise((resolve, reject) => {
        const shouldFail = Math.random() < 0.7;
        if (shouldFail) {
          reject(new Error('Operation failed'));
        } else {
          resolve('Operation succeeded');
        }
      });
    }
    
    const operation = retry.operation({
      retries: 5, // Number of retries
      factor: 2, // Exponential backoff factor
      minTimeout: 1000, // Minimum timeout between retries
      maxTimeout: 5000, // Maximum timeout between retries
    });
    
    operation.attempt(async (currentAttempt) => {
      try {
        const result = await unreliableFunction();
        console.log(result);
      } catch (error) {
        console.error(`Attempt ${currentAttempt} failed: ${error.message}`);
        if (operation.retry(error)) {
          console.log(`Retrying... (Attempt ${currentAttempt + 1})`);
        } else {
          console.error('All attempts failed.');
        }
      }
    });
    
  • p-retry:

    Example of p-retry:

    const pRetry = require('p-retry');
    
    async function unreliableFunction() {
      // Simulate a function that fails randomly
      const shouldFail = Math.random() < 0.7;
      if (shouldFail) {
        throw new Error('Failed');
      }
      return 'Success!';
    }
    
    async function main() {
      try {
        const result = await pRetry(unreliableFunction, {
          retries: 3, // Number of retries
          minTimeout: 1000, // Minimum timeout between retries
        });
        console.log('Result:', result);
      } catch (error) {
        console.error('Operation failed after retries:', error);
      }
    }
    
    main();
    
  • promise-retry:

    Example of promise-retry:

    const promiseRetry = require('promise-retry');
    
    function unreliableApiCall(retry, number) {
      console.log(`Attempt number: ${number}`);
      // Simulate a failing API call
      return new Promise((resolve, reject) => {
        const shouldFail = Math.random() < 0.5;
        if (shouldFail) {
          // Call retry() to indicate that the operation failed and should be retried
          retry(new Error('API call failed'));
        } else {
          resolve('API call succeeded');
        }
      });
    }
    
    promiseRetry((retry) => unreliableApiCall(retry), {
      retries: 5, // Number of retries
      minTimeout: 1000, // Minimum timeout between retries
      maxTimeout: 5000, // Maximum timeout between retries
    }).then((result) => {
      console.log(result);
    }).catch((error) => {
      console.error('Operation failed after retries:', error);
    });
    
  • async-retry:

    Example of async-retry:

    const retry = require('async-retry');
    
    async function fetchData() {
      // Simulate a function that may fail
      throw new Error('Network error');
    }
    
    async function main() {
      try {
        const result = await retry(async (bail) => {
          // If you want to stop retrying, call `bail` with an error
          // bail(new Error('Stop retrying'));
          return await fetchData();
        }, {
          retries: 5, // Number of retries
          factor: 2, // Exponential backoff factor
          minTimeout: 1000, // Minimum timeout between retries
          maxTimeout: 5000, // Maximum timeout between retries
        });
        console.log('Result:', result);
      } catch (error) {
        console.error('Failed after retries:', error);
      }
    }
    
    main();
    
  • retry-axios:

    Example of retry-axios:

    const axios = require('axios');
    const { setup } = require('retry-axios');
    
    // Create an Axios instance
    const axiosInstance = axios.create();
    
    // Setup retry-axios
    setup(axiosInstance, {
      retries: 3, // Number of retries
      retryDelay: (retryCount) => {
        return retryCount * 1000; // Delay between retries (in milliseconds)
      },
    });
    
    async function fetchData() {
      try {
        const response = await axiosInstance.get('https://api.example.com/data');
        console.log('Data:', response.data);
      } catch (error) {
        console.error('Request failed:', error);
      }
    }
    
    fetchData();
    
How to Choose: retry vs p-retry vs promise-retry vs async-retry vs retry-axios
  • retry:

    Choose retry if you require a comprehensive and feature-rich library that supports retrying both asynchronous and synchronous operations with advanced configuration options. It is ideal for more complex use cases where you need fine-grained control over the retry process, including support for exponential backoff, custom retry strategies, and event hooks.

  • p-retry:

    Choose p-retry if you want a lightweight and promise-based library that focuses on retrying failed asynchronous operations with a clean and intuitive API. It is particularly useful for scenarios where you need to retry a single promise-returning function and want to keep your code minimal and easy to understand.

  • promise-retry:

    Choose promise-retry if you need a library that provides a straightforward way to retry promise-based operations with support for customizable retry delays and backoff strategies. It is well-suited for situations where you want to retry a specific promise-returning function multiple times before giving up, and you want to have control over the retry logic.

  • async-retry:

    Choose async-retry if you need a simple and flexible solution for retrying asynchronous functions with support for exponential backoff and customizable retry strategies. It is ideal for general-purpose use cases where you want to easily integrate retry logic into your existing async functions.

  • retry-axios:

    Choose retry-axios if you are working with Axios for making HTTP requests and need a solution that integrates seamlessly with it to automatically retry failed requests. This library is particularly useful for handling transient network errors in API calls, and it allows you to configure retry logic directly within your Axios instance.

README for retry

Build Status codecov

retry

Abstraction for exponential and custom retry strategies for failed operations.

Installation

npm install retry

Current Status

This module has been tested and is ready to be used.

Tutorial

The example below will retry a potentially failing dns.resolve operation 10 times using an exponential backoff strategy. With the default settings, this means the last attempt is made after 17 minutes and 3 seconds.

var dns = require('dns');
var retry = require('retry');

function faultTolerantResolve(address, cb) {
  var operation = retry.operation();

  operation.attempt(function(currentAttempt) {
    dns.resolve(address, function(err, addresses) {
      if (operation.retry(err)) {
        return;
      }

      cb(err ? operation.mainError() : null, addresses);
    });
  });
}

faultTolerantResolve('nodejs.org', function(err, addresses) {
  console.log(err, addresses);
});

Of course you can also configure the factors that go into the exponential backoff. See the API documentation below for all available settings. currentAttempt is an int representing the number of attempts so far.

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

API

retry.operation([options])

Creates a new RetryOperation object. options is the same as retry.timeouts()'s options, with three additions:

  • forever: Whether to retry forever, defaults to false.
  • unref: Whether to unref the setTimeout's, defaults to false.
  • maxRetryTime: The maximum time (in milliseconds) that the retried operation is allowed to run. Default is Infinity.

retry.timeouts([options])

Returns an array of timeouts. All time options and return values are in milliseconds. If options is an array, a copy of that array is returned.

options is a JS object that can contain any of the following keys:

  • retries: The maximum amount of times to retry the operation. Default is 10. Seting this to 1 means do it once, then retry it once.
  • factor: The exponential factor to use. Default is 2.
  • minTimeout: The number of milliseconds before starting the first retry. Default is 1000.
  • maxTimeout: The maximum number of milliseconds between two retries. Default is Infinity.
  • randomize: Randomizes the timeouts by multiplying with a factor between 1 to 2. Default is false.

The formula used to calculate the individual timeouts is:

Math.min(random * minTimeout * Math.pow(factor, attempt), maxTimeout)

Have a look at this article for a better explanation of approach.

If you want to tune your factor / times settings to attempt the last retry after a certain amount of time, you can use wolfram alpha. For example in order to tune for 10 attempts in 5 minutes, you can use this equation:

screenshot

Explaining the various values from left to right:

  • k = 0 ... 9: The retries value (10)
  • 1000: The minTimeout value in ms (1000)
  • x^k: No need to change this, x will be your resulting factor
  • 5 * 60 * 1000: The desired total amount of time for retrying in ms (5 minutes)

To make this a little easier for you, use wolfram alpha to do the calculations:

http://www.wolframalpha.com/input/?i=Sum%5B1000*x^k%2C+{k%2C+0%2C+9}%5D+%3D+5+*+60+*+1000

retry.createTimeout(attempt, opts)

Returns a new timeout (integer in milliseconds) based on the given parameters.

attempt is an integer representing for which retry the timeout should be calculated. If your retry operation was executed 4 times you had one attempt and 3 retries. If you then want to calculate a new timeout, you should set attempt to 4 (attempts are zero-indexed).

opts can include factor, minTimeout, randomize (boolean) and maxTimeout. They are documented above.

retry.createTimeout() is used internally by retry.timeouts() and is public for you to be able to create your own timeouts for reinserting an item, see issue #13.

retry.wrap(obj, [options], [methodNames])

Wrap all functions of the obj with retry. Optionally you can pass operation options and an array of method names which need to be wrapped.

retry.wrap(obj)

retry.wrap(obj, ['method1', 'method2'])

retry.wrap(obj, {retries: 3})

retry.wrap(obj, {retries: 3}, ['method1', 'method2'])

The options object can take any options that the usual call to retry.operation can take.

new RetryOperation(timeouts, [options])

Creates a new RetryOperation where timeouts is an array where each value is a timeout given in milliseconds.

Available options:

  • forever: Whether to retry forever, defaults to false.
  • unref: Wether to unref the setTimeout's, defaults to false.

If forever is true, the following changes happen:

  • RetryOperation.errors() will only output an array of one item: the last error.
  • RetryOperation will repeatedly use the timeouts array. Once all of its timeouts have been used up, it restarts with the first timeout, then uses the second and so on.

retryOperation.errors()

Returns an array of all errors that have been passed to retryOperation.retry() so far. The returning array has the errors ordered chronologically based on when they were passed to retryOperation.retry(), which means the first passed error is at index zero and the last is at the last index.

retryOperation.mainError()

A reference to the error object that occured most frequently. Errors are compared using the error.message property.

If multiple error messages occured the same amount of time, the last error object with that message is returned.

If no errors occured so far, the value is null.

retryOperation.attempt(fn, timeoutOps)

Defines the function fn that is to be retried and executes it for the first time right away. The fn function can receive an optional currentAttempt callback that represents the number of attempts to execute fn so far.

Optionally defines timeoutOps which is an object having a property timeout in miliseconds and a property cb callback function. Whenever your retry operation takes longer than timeout to execute, the timeout callback function cb is called.

retryOperation.try(fn)

This is an alias for retryOperation.attempt(fn). This is deprecated. Please use retryOperation.attempt(fn) instead.

retryOperation.start(fn)

This is an alias for retryOperation.attempt(fn). This is deprecated. Please use retryOperation.attempt(fn) instead.

retryOperation.retry(error)

Returns false when no error value is given, or the maximum amount of retries has been reached.

Otherwise it returns true, and retries the operation after the timeout for the current attempt number.

retryOperation.stop()

Allows you to stop the operation being retried. Useful for aborting the operation on a fatal error etc.

retryOperation.reset()

Resets the internal state of the operation object, so that you can call attempt() again as if this was a new operation object.

retryOperation.attempts()

Returns an int representing the number of attempts it took to call fn before it was successful.

License

retry is licensed under the MIT license.

Changelog

0.10.0 Adding stop functionality, thanks to @maxnachlinger.

0.9.0 Adding unref functionality, thanks to @satazor.

0.8.0 Implementing retry.wrap.

0.7.0 Some bug fixes and made retry.createTimeout() public. Fixed issues #10, #12, and #13.

0.6.0 Introduced optional timeOps parameter for the attempt() function which is an object having a property timeout in milliseconds and a property cb callback function. Whenever your retry operation takes longer than timeout to execute, the timeout callback function cb is called.

0.5.0 Some minor refactoring.

0.4.0 Changed retryOperation.try() to retryOperation.attempt(). Deprecated the aliases start() and try() for it.

0.3.0 Added retryOperation.start() which is an alias for retryOperation.try().

0.2.0 Added attempts() function and parameter to retryOperation.try() representing the number of attempts it took to call fn().