aveazul
Version:
Bluebird drop-in replacement built on native Promise
209 lines (162 loc) • 7.25 kB
Markdown
# AveAzul.js
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.
## Purpose
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.
## Features
- Built on native Promises
- Implements most commonly used Bluebird methods
- Comprehensive test suite ensuring compatibility
## Requirements
- node.js version >= 12
## Installation
```bash
npm install aveazul
```
## Usage
```javascript
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 } };
}
);
```
## Migration from Bluebird
For most applications, migrating from Bluebird to AveAzul should be as simple as:
```javascript
// 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
## API
### Instance Methods
- `tap(fn)` - Execute side effects and return original value
- `filter(fn)` - Filter array elements
- `map(fn)` - Transform array elements
- `mapSeries(fn)` - Transform array elements sequentially
- `return(value)` - Inject a new value
- `each(fn)` - Iterate over array elements
- `delay(ms)` - Delay resolution
- `timeout(ms, message?)` - Reject after specified time
- `props(obj)` - Resolve object properties
- `spread(fn)` - Apply array values as arguments to function
- `tapCatch(fn)` - Execute side effects on rejection
- `reduce(fn, initialValue?)` - Reduce array elements
- `some(count)` - Resolves when a specified number of promises in the array have resolved
- `throw(reason)` - Return rejected promise
- `catchThrow(reason)` - Catch and throw new error
- `catchReturn(value)` - Catch and return value
- `get(propertyPath)` - Retrieve property value
- `disposer(fn)` - Create a disposer for use with AveAzul.using() for resource cleanup
- `any()` - Resolves when any promise in the iterable resolves, rejecting if all reject
- `all()` - Like Promise.all(), resolves when all promises resolve, rejects if any reject
- `call(propertyName, ...args)` - Call a method on the resolved value with the provided arguments
- `asCallback(callback, options?)` - Register a Node-style callback that handles the resolution or rejection
- `error(handler)` - Like catch(), but only catches operational errors, letting programmer errors bubble up
### Static Methods
- `delay(ms, value?)` - Resolve after specified time
- `map(value, fn)` - Transform array elements
- `mapSeries(value, fn)` - Transform array elements one at a time in sequence
- `try(fn)` - Wrap sync/async functions
- `props(obj)` - Resolve object properties
- `defer()` - Create a deferred promise
- `promisify(fn, options?)` - Convert callback-style functions to promises (preserves original function properties)
- `fromNode(fn, options?)` - Convert Node-style callback functions to promise-returning functions
- `fromCallback(fn, options?)` - Alias for fromNode
- `each(items, fn)` - Iterate over array elements
- `reduce(array, fn, initialValue?)` - Reduce array elements
- `some(promises, count)` - Wait for a specified number of promises to be fulfilled
- `method(fn)` - Creates a method that returns a promise resolving to the value returned by the original function
- `throw(reason)` - Return rejected promise
- `promisifyAll(target, options?)` - Convert all methods of an object/class to promises
- `using(resources, fn)` - Manage resources with automatic cleanup
- `join(...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
### Error Types
- `AveAzul.OperationalError` - Error type for representing expected operational errors (network failures, validation errors, etc.)
### PromisifyAll Options
- `suffix` (default: 'Async') - Suffix to append to promisified method names
- `filter` - Filter function to determine which methods to promisify
- `promisifier` - Custom function to handle promisification
- `multiArgs` (default: false) - Whether to support multiple callback arguments
## Development
```bash
# 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
```
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## License
Apache-2.0
## Author
Joel Chen, with assistant from Cursor Claude-3.7-sonnet