async-retry vs backoff vs exponential-backoff vs promise-retry vs retry
Retry Mechanisms in JavaScript
async-retrybackoffexponential-backoffpromise-retryretrySimilar Packages:

Retry Mechanisms in JavaScript

Retry mechanisms in JavaScript are techniques used to automatically attempt a failed operation multiple times before giving up. This is particularly useful for handling transient errors, such as network failures or temporary unavailability of a service. By implementing a retry strategy, developers can improve the resilience of their applications, reduce the likelihood of failures, and enhance the user experience. These mechanisms can be customized with parameters like the number of retries, delay between attempts, and backoff strategies to control how retries are performed. The following libraries provide various implementations of retry mechanisms in JavaScript, each with its own features and use cases.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
async-retry01,908-305 years agoMIT
backoff0336-1110 years agoMIT
exponential-backoff040655.2 kB65 months agoApache-2.0
promise-retry0317-116 years agoMIT
retry01,260-195 years agoMIT

Feature Comparison: async-retry vs backoff vs exponential-backoff vs promise-retry vs retry

Backoff Strategies

  • async-retry:

    async-retry allows you to define custom backoff strategies, including exponential backoff, but does not provide built-in support for multiple backoff types.

  • backoff:

    backoff provides a wide range of backoff strategies, including exponential, linear, and custom backoff, with the ability to easily switch between them and configure their behavior.

  • exponential-backoff:

    exponential-backoff focuses solely on exponential backoff, providing a simple and efficient implementation for scenarios where this strategy is sufficient.

  • promise-retry:

    promise-retry supports customizable delays between retries, but does not have built-in support for multiple backoff strategies. You can implement your own logic for backoff if needed.

  • retry:

    retry supports various backoff strategies, including exponential and linear, and allows for extensive customization of the backoff behavior through options.

Error Handling

  • async-retry:

    async-retry allows you to handle errors and decide whether to retry based on the error type or message. You can implement custom logic to determine when to stop retrying.

  • backoff:

    backoff provides event hooks for error handling, allowing you to respond to errors, retries, and completion events. This makes it easy to integrate custom error handling logic.

  • exponential-backoff:

    exponential-backoff provides basic error handling, but it is up to the developer to implement custom logic for handling errors and determining when to stop retrying.

  • promise-retry:

    promise-retry allows you to handle errors and customize the retry logic based on the error. You can provide a function to determine whether to retry based on the error type.

  • retry:

    retry allows for custom error handling and provides options to specify which errors should trigger a retry. You can implement logic to handle specific error types.

Promise Support

  • async-retry:

    async-retry is designed for asynchronous operations and works seamlessly with promises. It supports both async/await and promise-based APIs.

  • backoff:

    backoff is primarily focused on backoff strategies and does not provide built-in support for promises. However, it can be integrated with promise-based code.

  • exponential-backoff:

    exponential-backoff is designed for use with promises, making it suitable for retrying asynchronous operations that return promises.

  • promise-retry:

    promise-retry is specifically designed for promise-based operations, making it easy to integrate into async functions and handle retries with promises.

  • retry:

    retry supports both callback and promise-based APIs, allowing for flexibility in how you implement retry logic in your code.

Customization

  • async-retry:

    async-retry offers a high degree of customization, allowing you to define the number of retries, backoff strategy, and error handling logic. It is flexible and easy to configure.

  • backoff:

    backoff is highly customizable, allowing you to configure backoff strategies, error handling, and event listeners. It provides a lot of flexibility for complex use cases.

  • exponential-backoff:

    exponential-backoff is simple and lightweight, but it has limited customization options. It is best suited for scenarios where a straightforward exponential backoff implementation is needed.

  • promise-retry:

    promise-retry allows for customization of the retry count, delay, and error handling. It is straightforward to use and configure, making it suitable for most use cases.

  • retry:

    retry provides extensive customization options for retries, delays, and backoff strategies. It is versatile and can be configured to handle a wide range of retry scenarios.

Ease of Use: Code Examples

  • async-retry:

    Retrying an asynchronous operation with 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 fetched:', result);
      } catch (error) {
        console.error('Failed to fetch data:', error);
      }
    }
    
    main();
    
  • backoff:

    Using backoff for exponential backoff

    const backoff = require('backoff');
    
    const operation = backoff.call(function (callback) {
      // Simulate a failing operation
      console.log('Attempting operation...');
      callback(new Error('Operation failed'));
    });
    
    operation.failAfter(5); // Fail after 5 attempts
    operation.on('backoff', function (number, delay) {
      console.log(`Backoff #${number} for ${delay}ms`);
    });
    operation.on('fail', function () {
      console.log('Operation failed after multiple attempts.');
    });
    operation.start();
    
  • exponential-backoff:

    Exponential backoff example

    const exponentialBackoff = require('exponential-backoff');
    
    function unreliableFunction() {
      return new Promise((resolve, reject) => {
        const success = Math.random() > 0.7; // 30% chance of failure
        setTimeout(() => (success ? resolve('Success!') : reject(new Error('Failed'))), 1000);
      });
    }
    
    const backoff = exponentialBackoff.backoff({
      initialDelay: 1000,
      maxDelay: 16000,
      multiplier: 2,
    });
    
    backoff.retry(unreliableFunction)
      .then(result => console.log(result))
      .catch(error => console.error(error));
    
  • promise-retry:

    Retrying a promise-based function with promise-retry

    const promiseRetry = require('promise-retry');
    
    function unreliableApiCall(retry, attempt) {
      console.log(`Attempt ${attempt}`);
      return new Promise((resolve, reject) => {
        const success = Math.random() > 0.5; // 50% chance of failure
        setTimeout(() => (success ? resolve('Data') : reject(new Error('Failed'))), 1000);
      });
    }
    
    promiseRetry((retry) => {
      return unreliableApiCall(retry);
    }, {
      retries: 5,
      minTimeout: 1000,
      maxTimeout: 5000,
    }).then(console.log).catch(console.error);
    
  • retry:

    Using retry for a callback-based operation

    const retry = require('retry');
    
    const operation = retry.operation({
      retries: 5,
      factor: 2,
      minTimeout: 1000,
      maxTimeout: 5000,
    });
    
    operation.attempt((currentAttempt) => {
      console.log(`Attempt ${currentAttempt}`);
      // Simulate a failing operation
      const error = new Error('Operation failed');
      if (operation.retry(error)) {
        console.log(`Retrying...`);
      } else {
        console.error(`Failed after ${operation.attempts()} attempts`);
      }
    });
    

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

  • async-retry:

    Choose async-retry if you need a simple and flexible solution for retrying asynchronous operations with customizable retry logic and backoff strategies.

  • backoff:

    Choose backoff if you require a comprehensive library that supports various backoff strategies, including exponential, linear, and custom backoff, with built-in event handling.

  • exponential-backoff:

    Choose exponential-backoff if you specifically need a lightweight implementation of exponential backoff for retrying operations, especially in scenarios like API calls or network requests.

  • promise-retry:

    Choose promise-retry if you want a straightforward way to retry promise-based operations with support for customizable retry counts and delays, while keeping the API simple and easy to use.

  • retry:

    Choose retry if you need a versatile library that supports both callback and promise-based APIs for retrying operations, with extensive customization options for retries, delays, and backoff strategies.

README for async-retry

async-retry

Retrying made simple, easy, and async.

Usage

// Packages
const retry = require('async-retry');
const fetch = require('node-fetch');

await retry(
  async (bail) => {
    // if anything throws, we retry
    const res = await fetch('https://google.com');

    if (403 === res.status) {
      // don't retry upon 403
      bail(new Error('Unauthorized'));
      return;
    }

    const data = await res.text();
    return data.substr(0, 500);
  },
  {
    retries: 5,
  }
);

API

retry(retrier : Function, opts : Object) => Promise
  • The supplied function can be async or not. In other words, it can be a function that returns a Promise or a value.
  • The supplied function receives two parameters
    1. A Function you can invoke to abort the retrying (bail)
    2. A Number identifying the attempt. The absolute first attempt (before any retries) is 1.
  • The opts are passed to node-retry. Read its docs
    • retries: The maximum amount of times to retry the operation. Default is 10.
    • 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 true.
    • onRetry: an optional Function that is invoked after a new retry is performed. It's passed the Error that triggered it as a parameter.

Authors