AveAzul ("Blue Bird" in Spanish) serves as a near drop-in replacement for Bluebird. It's built on native Promise, by extending it with the familiar utility methods from Bluebird.
The primary goal is to help migrate legacy code, that uses Bluebird APIs extensively, to native Promises. While not a 100% drop-in replacement (some aspects of Bluebird simply can't be replicated), it offers a practical migration path with minimal changes for most cases.
Further, if you like Bluebird's API but want to use native Promises, AveAzul gives you both - familiar Bluebird methods built on native Promise.
- Built on native Promises
- Implements most commonly used Bluebird methods
- Comprehensive test suite ensuring compatibility
- node.js version >= 12
npm install aveazul
const AveAzul = require("aveazul");
// Basic Promise usage
const promise = new AveAzul((resolve) => resolve(42));
promise.then((value) => console.log(value)); // 42
// Utility methods
AveAzul.resolve([1, 2, 3])
.map((x) => x * 2)
.filter((x) => x > 2)
.then((result) => console.log(result)); // [4, 6]
// Wait for at least 2 promises to be fulfilled
const fetchUrls = [
fetch("https://api.example.com/data1"),
fetch("https://api.example.com/data2"),
fetch("https://api.example.com/data3"),
fetch("https://api.example.com/data4"),
];
AveAzul.some(fetchUrls, 2).then((results) =>
console.log(`Got the first 2 successful results`)
);
// Process items sequentially with mapSeries
AveAzul.resolve([1, 2, 3])
.mapSeries(async (x) => {
// Each item is processed only after the previous one completes
await new Promise((resolve) => setTimeout(resolve, 100));
return x * 2;
})
.then((result) => console.log(result)); // [2, 4, 6]
// Promisify callback-style functions
const fs = require("fs");
const readFile = AveAzul.promisify(fs.readFile);
readFile("file.txt").then((content) => console.log(content));
// Properties from the original function are preserved
console.log(readFile.length); // Original function's length property
// Promisify all methods of an object
const obj = {
method(cb) {
cb(null, "result");
},
};
AveAzul.promisifyAll(obj);
obj.methodAsync().then((result) => console.log(result)); // 'result'
// Resource management with disposer and using
const getResource = () => {
return AveAzul.resolve({
data: "important data",
close: () => console.log("Resource closed!"),
}).disposer((resource) => resource.close());
};
AveAzul.using(getResource(), (resource) => {
console.log(resource.data); // "important data"
return AveAzul.resolve("operation completed");
}).then((result) => {
console.log(result); // "operation completed"
// Resource is automatically closed here, even if an error occurred
});
// Using spread to apply array results as arguments
AveAzul.all([getUser(1), getPosts(1), getComments(1)]).spread(
(user, posts, comments) => {
// Instead of using .then(([user, posts, comments]) => {...})
console.log(
`User ${user.name} has ${posts.length} posts and ${comments.length} comments`
);
return { user, activity: { posts, comments } };
}
);
For most applications, migrating from Bluebird to AveAzul should be as simple as:
// From
const Promise = require("bluebird");
// To
const Promise = require("aveazul");
Key differences to be aware of:
- Some advanced debugging features are not available
- Performance characteristics may differ
- A few very specialized methods not available
tap(fn)
- Execute side effects and return original valuefilter(fn)
- Filter array elementsmap(fn)
- Transform array elementsmapSeries(fn)
- Transform array elements sequentiallyreturn(value)
- Inject a new valueeach(fn)
- Iterate over array elementsdelay(ms)
- Delay resolutiontimeout(ms, message?)
- Reject after specified timeprops(obj)
- Resolve object propertiesspread(fn)
- Apply array values as arguments to functiontapCatch(fn)
- Execute side effects on rejectionreduce(fn, initialValue?)
- Reduce array elementssome(count)
- Resolves when a specified number of promises in the array have resolvedthrow(reason)
- Return rejected promisecatchThrow(reason)
- Catch and throw new errorcatchReturn(value)
- Catch and return valueget(propertyPath)
- Retrieve property valuedisposer(fn)
- Create a disposer for use with AveAzul.using() for resource cleanupany()
- Resolves when any promise in the iterable resolves, rejecting if all rejectall()
- Like Promise.all(), resolves when all promises resolve, rejects if any rejectcall(propertyName, ...args)
- Call a method on the resolved value with the provided argumentsasCallback(callback, options?)
- Register a Node-style callback that handles the resolution or rejectionerror(handler)
- Like catch(), but only catches operational errors, letting programmer errors bubble up
delay(ms, value?)
- Resolve after specified timemap(value, fn)
- Transform array elementsmapSeries(value, fn)
- Transform array elements one at a time in sequencetry(fn)
- Wrap sync/async functionsprops(obj)
- Resolve object propertiesdefer()
- Create a deferred promisepromisify(fn, options?)
- Convert callback-style functions to promises (preserves original function properties)fromNode(fn, options?)
- Convert Node-style callback functions to promise-returning functionsfromCallback(fn, options?)
- Alias for fromNodeeach(items, fn)
- Iterate over array elementsreduce(array, fn, initialValue?)
- Reduce array elementssome(promises, count)
- Wait for a specified number of promises to be fulfilledmethod(fn)
- Creates a method that returns a promise resolving to the value returned by the original functionthrow(reason)
- Return rejected promisepromisifyAll(target, options?)
- Convert all methods of an object/class to promisesusing(resources, fn)
- Manage resources with automatic cleanupjoin(...values, handler?)
- Wait for multiple promises and pass their resolved values as separate arguments to the handler function. If no handler is provided, behaves like Promise.all
AveAzul.OperationalError
- Error type for representing expected operational errors (network failures, validation errors, etc.)
suffix
(default: 'Async') - Suffix to append to promisified method namesfilter
- Filter function to determine which methods to promisifypromisifier
- Custom function to handle promisificationmultiArgs
(default: false) - Whether to support multiple callback arguments
# Install dependencies
npm install
# Run tests
npm test
npm run test:watch
npm run test:coverage
# Test against Bluebird for compatibility
npm run jest:bluebird -- test/[name].test.js
Contributions are welcome! Please feel free to submit a Pull Request.
Apache-2.0
Joel Chen, with assistant from Cursor Claude-3.7-sonnet