retry vs p-retry vs promise-retry vs async-retry vs retry-axios vs promise-poller
JavaScript Retry Libraries
retryp-retrypromise-retryasync-retryretry-axiospromise-pollerSimilar Packages:
JavaScript Retry Libraries

Retry libraries in JavaScript provide mechanisms to automatically re-attempt failed asynchronous operations, such as network requests or database queries. These libraries help improve the resilience of applications by handling transient errors (temporary issues that may resolve on their own) without requiring manual intervention. They offer configurable options like the number of retries, delay between attempts, and exponential backoff strategies, allowing developers to customize the retry behavior based on their specific use cases. By implementing retries, applications can reduce the impact of temporary failures, enhance user experience, and ensure more reliable data processing.

Npm Package Weekly Downloads Trend
3 Years
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
retry58,229,9661,260-194 years agoMIT
p-retry22,173,52596023.1 kB32 months agoMIT
promise-retry20,917,345317-115 years agoMIT
async-retry14,589,2001,903-304 years agoMIT
retry-axios1,266,54149957.8 kB0a month agoApache-2.0
promise-poller14,810119-86 years agoMIT
Feature Comparison: retry vs p-retry vs promise-retry vs async-retry vs retry-axios vs promise-poller

Retry Mechanism

  • retry:

    retry is a versatile library that supports retrying both synchronous and asynchronous functions. It provides extensive configuration options, including customizable retry counts, delay strategies, and error handling.

  • p-retry:

    p-retry focuses on retrying promise-returning functions. It offers a clean API and allows you to specify the number of retries, delay between attempts, and a function to determine if a retry should occur.

  • promise-retry:

    promise-retry allows you to retry a promise-returning function with customizable retry delays. You can specify the number of retries, the delay between attempts, and provide a function to calculate the delay dynamically.

  • async-retry:

    async-retry provides a simple way to retry asynchronous functions with customizable retry logic. It supports exponential backoff and allows you to define when to retry based on the error type.

  • retry-axios:

    retry-axios integrates with Axios to provide automatic retry functionality for HTTP requests. It allows you to configure retry behavior, such as the number of retries and delay between attempts, directly on your Axios instance.

  • promise-poller:

    promise-poller is designed for polling a promise-based function until it resolves or reaches a maximum number of attempts. It is useful for scenarios where you need to repeatedly check the status of an operation.

Customization

  • retry:

    retry offers extensive customization options, including the ability to define your own retry strategy, set maximum retries, and customize delay functions. It is highly configurable and suitable for complex retry scenarios.

  • p-retry:

    p-retry offers customization for the number of retries, delay between attempts, and the ability to provide a custom retry strategy function. It is designed to be simple and intuitive while allowing for flexibility.

  • promise-retry:

    promise-retry provides customization for the number of retries, delay between retries, and the ability to use a custom delay function. It allows you to define how retries should be handled in a straightforward manner.

  • async-retry:

    async-retry allows for significant customization, including the ability to define your own retry logic, set maximum retries, and customize the delay between retries. It also supports asynchronous delay functions.

  • retry-axios:

    retry-axios allows customization of the retry behavior for Axios requests, including the number of retries, delay between retries, and the ability to specify which HTTP status codes should trigger a retry.

  • promise-poller:

    promise-poller allows customization of the polling interval, maximum attempts, and the function used to check the promise. You can easily adjust these parameters to fit your use case.

Integration with Promises

  • retry:

    retry supports both synchronous and asynchronous functions, providing flexibility in how you implement retries. It can handle any function type, including those that return promises.

  • p-retry:

    p-retry is built specifically for promise-returning functions, ensuring a smooth integration with asynchronous code. It is lightweight and focuses solely on retrying promises.

  • promise-retry:

    promise-retry is focused on retrying promise-returning functions, making it a great choice for async operations that may fail and need to be retried.

  • async-retry:

    async-retry is designed for asynchronous functions and works seamlessly with promises. It can handle any function that returns a promise, making it versatile for various async operations.

  • retry-axios:

    retry-axios is specifically designed for Axios, a popular promise-based HTTP client. It adds retry functionality to Axios requests, making it easy to handle failed HTTP calls.

  • promise-poller:

    promise-poller integrates well with promise-based functions, allowing you to poll a promise until it resolves. It is particularly useful for scenarios where you need to wait for a promise to complete.

Code Example

  • retry:

    Example of retry

    const retry = require('retry');
    
    function unreliableTask() {
      // Simulate a task that may fail
      return new Promise((resolve, reject) => {
        const random = Math.random();
        if (random < 0.7) {
          // 70% chance of failure
          reject(new Error('Task failed'));
        } else {
          resolve('Task succeeded');
        }
      });
    }
    
    const operation = retry.operation({
      retries: 5,
      factor: 2,
      minTimeout: 1000,
      maxTimeout: 4000,
    });
    
    operation.attempt(async (currentAttempt) => {
      try {
        const result = await unreliableTask();
        console.log(result);
      } catch (error) {
        console.error(`Attempt ${currentAttempt} failed: ${error.message}`);
        if (operation.retry(error)) {
          console.log(`Retrying... (Attempt ${operation.attempts()})`);
        }
      }
    });
    
  • p-retry:

    Example of p-retry

    const { pRetry } = require('p-retry');
    
    async function unreliableFunction() {
      // Simulate a function that fails
      throw new Error('Failed');
    }
    
    async function main() {
      try {
        const result = await pRetry(unreliableFunction, {
          retries: 5,
          onFailedAttempt: (error) => {
            console.log(`Attempt failed: ${error.message}`);
          },
        });
        console.log('Success:', result);
      } catch (error) {
        console.error('All attempts failed:', error);
      }
    }
    
    main();
    
  • promise-retry:

    Example of promise-retry

    const promiseRetry = require('promise-retry');
    
    function unreliableApiCall(retry, attempt) {
      // Simulate an API call that fails
      if (attempt < 3) {
        // Fail the first two attempts
        return retry(new Error('Temporary failure'));
      }
      // Succeed on the third attempt
      return 'Data from API';
    }
    
    promiseRetry((retry) => unreliableApiCall(retry, attempt), {
      retries: 5,
      factor: 2,
      minTimeout: 1000,
      maxTimeout: 4000,
    }).then((result) => {
      console.log('API call succeeded:', result);
    }).catch((error) => {
      console.error('API call 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(fetchData, {
          retries: 3,
          factor: 2,
          minTimeout: 1000,
          maxTimeout: 5000,
        });
        console.log('Data:', 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');
    
    const instance = axios.create();
    setup(instance, {
      retries: 3,
      retryDelay: (retryCount) => {
        return retryCount * 1000; // Exponential backoff
      },
    });
    
    async function makeRequest() {
      try {
        const response = await instance.get('https://httpbin.org/status/500');
        console.log('Response:', response.data);
      } catch (error) {
        console.error('Request failed:', error);
      }
    }
    
    makeRequest();
    
  • promise-poller:

    Example of promise-poller

    const promisePoller = require('promise-poller');
    
    async function pollerFunction() {
      // Simulate a polling function
      return new Promise((resolve, reject) => {
        const random = Math.random();
        if (random < 0.8) {
          // 80% chance to fail
          reject(new Error('Not ready'));
        } else {
          // 20% chance to succeed
          resolve('Success!');
        }
      });
    }
    
    async function main() {
      try {
        const result = await promisePoller({
          function: pollerFunction,
          interval: 1000,
          maxAttempts: 10,
        });
        console.log('Polling result:', result);
      } catch (error) {
        console.error('Polling failed:', error);
      }
    }
    
    main();
    
How to Choose: retry vs p-retry vs promise-retry vs async-retry vs retry-axios vs promise-poller
  • retry:

    Choose retry if you need a versatile library for retrying both synchronous and asynchronous functions, with extensive configuration options for retries, delays, and backoff strategies.

  • p-retry:

    Select p-retry if you want a lightweight library focused on retrying promises with a clean API and built-in support for customizable retry strategies.

  • promise-retry:

    Opt for promise-retry if you require a straightforward way to retry promise-returning functions with support for custom retry delays and error handling.

  • async-retry:

    Choose async-retry if you need a simple and flexible solution for retrying asynchronous functions with support for exponential backoff and custom retry logic.

  • retry-axios:

    Select retry-axios if you are working with Axios and want to add automatic retry functionality to your HTTP requests with minimal setup.

  • promise-poller:

    Use promise-poller when you need to poll a promise-based function at regular intervals until it resolves or reaches a maximum number of attempts.

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().