Promise Retry Utility (Bluebird-focused)
The `retry-promise` package (version 1.0.0), last published in November 2015, provides a small utility function for automatically retrying promise-returning operations. It was explicitly designed to work with Bluebird Promises and implements a basic retry mechanism with configurable maximum attempts (`opts.max`) and a linear backoff strategy. The delay between retries is calculated as `attempt_number * opts.backoff`, meaning each subsequent retry waits proportionally longer. Given its age and lack of updates for nearly a decade, this package is considered abandoned. It lacks support for modern JavaScript features like native Promises or ES Modules and does not offer advanced retry strategies (e.g., jitter, custom error predicates) found in more actively maintained alternatives such as `p-retry` or `ts-retry-promise`. For new projects, developers should consider these contemporary libraries over `retry-promise`.
Common errors
-
TypeError: (intermediate value) is not a function
cause This typically occurs when `retry-promise` expects a Bluebird Promise instance, but it receives a non-callable value, possibly due to direct use of native Promises or an incompatible Promise implementation.fixEnsure that Bluebird is being used or that the function passed to `retry` explicitly returns a Bluebird Promise. If migrating is not an option, you might need to manually adapt Bluebird into your project. -
TypeError: Cannot read properties of undefined (reading 'then')
cause The function provided to `retry` did not return a Promise or a 'thenable' object, causing `retry-promise` to fail when attempting to chain operations.fixModify the function passed to `retry` to ensure it always returns a Promise, regardless of its execution path.
Warnings
- breaking The `retry-promise` package is effectively abandoned, with its last update occurring approximately ten years ago. It is unlikely to receive further maintenance, bug fixes, or compatibility updates for modern JavaScript environments, native Promises, or ES Modules.
- gotcha The package explicitly targets 'bluebird Promises' but does not declare `bluebird` as a dependency. Using native JavaScript Promises or other Promise libraries directly might lead to unexpected behavior or errors if their implementations are not fully compatible with `retry-promise`'s internal workings.
- gotcha The backoff strategy is linear, calculating the delay as `attempt_number * opts.backoff`. This differs from exponential backoff strategies commonly found in modern retry libraries, which typically increase delays more aggressively to mitigate overloaded services.
Install
-
npm install retry-promise -
yarn add retry-promise -
pnpm add retry-promise
Imports
- retry
const retry = require('retry-promise');
Quickstart
const retry = require('retry-promise');
// Mock a User model that occasionally fails to demonstrate retries
let creationAttempts = 0;
const User = {
forge: function(data) {
return {
createOrLoad: function() {
return new Promise((resolve, reject) => {
creationAttempts++;
console.log(`[Mock User] Attempt ${creationAttempts} to create user ${data.email}`);
if (creationAttempts < 3) { // Simulate transient failure for the first 2 attempts
console.log(`[Mock User] Failed attempt ${creationAttempts}`);
return reject(new Error('Database temporarily unavailable'));
} else {
console.log(`[Mock User] Succeeded on attempt ${creationAttempts}`);
return resolve({ id: 1, email: data.email });
}
});
}
};
}
};
// Mock Express-like req/next for a runnable example
const req = {};
const next = (err) => {
if (err) {
console.error('Middleware error:', err.message);
} else {
console.log('Middleware successful. User:', req.user);
}
};
console.log('Starting retry operation...');
retry({ max: 3, backoff: 1000 }, function (attempt) {
console.log(`retry-promise callback - Attempt ${attempt}`);
return User
.forge({ email: 'test@example.com' })
.createOrLoad();
})
.then(function (user) {
req.user = user;
next();
})
.catch(function(error) {
console.error('[retry-promise] Final failure:', error.message);
next(error);
});