retry vs p-retry vs promise-retry vs exponential-backoff vs async-retry vs backoff
JavaScript Retry Libraries Comparison
1 Year
retryp-retrypromise-retryexponential-backoffasync-retrybackoffSimilar Packages:
What's JavaScript Retry Libraries?

These libraries provide mechanisms for retrying asynchronous operations that may fail due to transient errors, such as network requests or database queries. They help improve the robustness of applications by allowing developers to specify retry strategies, including the number of attempts, delays between attempts, and backoff strategies to handle failures gracefully. Each library has its unique features and use cases, making them suitable for different scenarios in web development.

Package Weekly Downloads Trend
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
retry42,508,5851,247-194 years agoMIT
p-retry17,626,38884513.2 kB175 months agoMIT
promise-retry16,123,449316-115 years agoMIT
exponential-backoff12,342,97936955.2 kB62 months agoApache-2.0
async-retry9,911,3131,871-304 years agoMIT
backoff719,246337-119 years agoMIT
Feature Comparison: retry vs p-retry vs promise-retry vs exponential-backoff vs async-retry vs backoff

Retry Strategy Customization

  • retry:

    retry supports a variety of retry strategies, including fixed, exponential, and custom delays, allowing for a broad range of use cases and flexibility in handling retries.

  • p-retry:

    p-retry offers a straightforward way to customize retry strategies through options such as retries, minTimeout, and maxTimeout, making it easy to adapt to different scenarios with minimal configuration.

  • promise-retry:

    promise-retry provides a simple interface for customizing retry behavior, including the number of retries and delay between attempts, which can be tailored to the specific needs of your application.

  • exponential-backoff:

    exponential-backoff focuses on implementing a classic exponential backoff strategy, allowing you to set parameters like base delay and maximum attempts, which are essential for network-related operations.

  • async-retry:

    async-retry allows you to define a custom retry strategy, including the number of attempts and delay between retries. You can specify a delay function that can vary based on the attempt number, giving you flexibility in handling retries.

  • backoff:

    backoff provides a simple API for defining exponential backoff strategies, allowing you to customize the initial delay, maximum delay, and factor for increasing the delay after each failure, making it suitable for handling rate limits.

Error Handling

  • retry:

    retry provides mechanisms for error handling, allowing you to specify which errors should trigger a retry and how to handle them, making it a versatile choice for various scenarios.

  • p-retry:

    p-retry includes built-in error handling that allows you to specify which errors should be retried, making it easier to manage retries based on specific error types.

  • promise-retry:

    promise-retry allows you to handle errors gracefully by specifying conditions under which retries should occur, giving you control over the retry logic based on the nature of the error.

  • exponential-backoff:

    exponential-backoff provides basic error handling by allowing you to define which errors should trigger a retry, ensuring that only transient errors are retried.

  • async-retry:

    async-retry allows you to specify a custom error filter, enabling you to decide which errors should trigger a retry. This feature helps in avoiding unnecessary retries for non-transient errors.

  • backoff:

    backoff does not have built-in error handling but can be combined with other libraries to manage errors effectively. It focuses primarily on the backoff strategy rather than error categorization.

Integration with Async/Await

  • retry:

    retry can be used with async/await, but it may require additional handling for async functions, as it is a more general-purpose library.

  • p-retry:

    p-retry is built with async/await in mind, allowing for a clean and straightforward integration into async functions, making it easy to implement retries in modern JavaScript applications.

  • promise-retry:

    promise-retry is designed for use with Promises and works well with async/await, making it a suitable choice for projects that rely on asynchronous programming patterns.

  • exponential-backoff:

    exponential-backoff can be integrated with async/await, but it is more focused on the backoff logic rather than providing a complete async handling solution.

  • async-retry:

    async-retry is designed to work seamlessly with async/await syntax, making it easy to integrate into modern JavaScript applications that utilize Promises.

  • backoff:

    backoff can be used with async/await, but it may require additional handling for Promises, as it primarily focuses on the backoff strategy rather than async operations directly.

Simplicity of Use

  • retry:

    retry offers a versatile API that can be used for both synchronous and asynchronous functions, but its general-purpose nature may require more configuration compared to specialized libraries.

  • p-retry:

    p-retry is designed to be user-friendly with a clean API that makes it easy to implement retries in asynchronous functions, making it a good choice for developers looking for simplicity.

  • promise-retry:

    promise-retry provides a simple and intuitive interface for retrying Promises, making it easy for developers to integrate into their applications without extensive configuration.

  • exponential-backoff:

    exponential-backoff is simple to use for implementing backoff strategies, but it may not provide as much flexibility in terms of error handling as other libraries.

  • async-retry:

    async-retry is known for its simplicity and ease of use, providing a minimalistic API that allows developers to quickly implement retry logic without much overhead.

  • backoff:

    backoff offers a straightforward API for defining backoff strategies, making it easy to implement without a steep learning curve, although it may require additional integration for error handling.

Community and Maintenance

  • retry:

    retry is widely used and has a strong community, making it a reliable choice for developers looking for a well-supported library.

  • p-retry:

    p-retry has a robust community and is actively maintained, ensuring that developers have access to support and updates as needed.

  • promise-retry:

    promise-retry is well-maintained and has a decent community, providing sufficient resources for developers looking to implement retry logic in their applications.

  • exponential-backoff:

    exponential-backoff is maintained but may not have as large a community as other libraries, which could impact the availability of community support and resources.

  • async-retry:

    async-retry is actively maintained and has a growing community, providing good support and documentation for developers looking to implement retry logic.

  • backoff:

    backoff has a smaller community but is still maintained, making it suitable for projects that require a focused backoff strategy without extensive support needs.

How to Choose: retry vs p-retry vs promise-retry vs exponential-backoff vs async-retry vs backoff
  • retry:

    Select retry if you need a more general-purpose library that can handle both synchronous and asynchronous functions. It offers a variety of retry strategies and is suitable for a wide range of use cases.

  • p-retry:

    Opt for p-retry if you prefer a Promise-based approach with a simple API for retrying asynchronous functions. It allows for easy integration with existing Promise-based code and provides built-in support for retry delays and custom error handling.

  • promise-retry:

    Choose promise-retry if you need a library that focuses specifically on retrying Promises with support for customizable retry strategies. It is particularly useful for handling failed Promise rejections in a controlled manner.

  • exponential-backoff:

    Use exponential-backoff if your primary requirement is to implement a classic exponential backoff algorithm with customizable parameters. This package is ideal for network requests that need to adhere to specific retry intervals that increase after each failure.

  • async-retry:

    Choose async-retry if you need a simple and flexible solution for retrying asynchronous functions with customizable retry logic and delay options. It is easy to integrate and works well with Promises and async/await syntax.

  • backoff:

    Select backoff if you want a library focused on implementing exponential backoff strategies. It provides a straightforward API for defining backoff strategies and is useful for scenarios where you want to avoid overwhelming a service with repeated requests.

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