Bluebird Promise Retry Utility
bluebird-retry is a utility library for Node.js and browsers that facilitates retrying an asynchronous operation until it successfully resolves. It leverages Bluebird promises for its core functionality and expects Bluebird to be provided as a peer dependency. The current stable version is 0.11.0. This package supports various retry mechanisms including regular intervals, exponential backoff with configurable limits, and an overall operation timeout. A key differentiator is its ability to conditionally retry based on a `predicate` (similar to Bluebird's filtered catch) and to explicitly stop the retry loop by throwing a `StopError`. While functional, the package appears to be in maintenance mode, with its last release (v0.11.0) occurring several years ago, and is primarily designed for CommonJS environments.
Common errors
-
Error: operation timed out
cause The retry operation exhausted its maximum number of attempts (`max_tries`) or exceeded its calculated `timeout` duration before the wrapped function succeeded.fixIncrease the `max_tries` option, or adjust `interval` and `backoff` to allow more attempts within the `timeout` period. Alternatively, debug the underlying function to understand why it's consistently failing and fix it. -
Promise is not defined
cause The `bluebird` library, which `bluebird-retry` depends on, has not been properly imported or is not available in the global scope/module context.fixEnsure `bluebird` is installed (`npm install bluebird`) and imported at the top of your file: `const Promise = require('bluebird');`. -
TypeError: retry.StopError is not a constructor
cause You are attempting to use `retry.StopError` but `retry` was not correctly imported or is not the object containing the `StopError` class.fixEnsure you are importing `bluebird-retry` using `const retry = require('bluebird-retry');` and then referencing `retry.StopError` correctly. Do not try to destructure `StopError` directly from the package import.
Warnings
- breaking The `bluebird` library was changed from a direct dependency to a peer dependency. Applications must now explicitly install `bluebird` alongside `bluebird-retry`.
- gotcha The `timeout` option does not create a real-time timeout, but rather computes a maximum number of attempts based on the `interval` and `backoff` options. If both `timeout` and `max_tries` are specified, the limit that comes first will apply.
- gotcha By default, `bluebird-retry` absorbs all intermediate rejection messages, and will only propagate the final error if the operation ultimately times out or reaches `max_tries`. This can make debugging initial failures difficult.
- deprecated The package uses `.try` and `.catch` aliases (`.attempt` and `.caught` respectively) for older browser support. While functionally equivalent in Bluebird, modern Bluebird versions and native Promises prefer `.try` (or direct `try/catch` with `async/await`) and `.catch`.
- gotcha As a package in maintenance mode (last update several years ago), it may not fully leverage modern JavaScript features like `async/await` directly without explicit Bluebird promisification, nor is it optimized for ESM environments without transpilation or bundler configuration.
Install
-
npm install bluebird-retry -
yarn add bluebird-retry -
pnpm add bluebird-retry
Imports
- retry
import retry from 'bluebird-retry';
const retry = require('bluebird-retry'); - retry.StopError
import { StopError } from 'bluebird-retry';const retry = require('bluebird-retry'); // ... then later ... throw new retry.StopError('message'); - Promise (from bluebird)
import { Promise } from 'bluebird';const Promise = require('bluebird');
Quickstart
const Promise = require('bluebird');
const retry = require('bluebird-retry');
let count = 0;
function myfunc() {
console.log('myfunc called ' + (++count) + ' times');
if (count < 3) {
// Simulate an asynchronous failure with a Bluebird rejection
return Promise.reject(new Error('fail the first two times'));
} else {
// Simulate an asynchronous success
return Promise.resolve('succeed the third time');
}
}
retry(myfunc, { max_tries: 5, interval: 500 })
.then(function(result) {
console.log(result);
})
.catch(function(err) {
console.error('Operation failed completely:', err.message);
});