Top Related Projects
Quick Overview
p-map is a JavaScript library that provides a way to map over promises concurrently. It allows you to run Promise-returning & async functions over a list of inputs with limited concurrency, which is useful for controlling the number of simultaneous operations when working with asynchronous tasks.
Pros
- Allows fine-grained control over concurrency, preventing potential system overload
- Supports both Promise-returning and async functions
- Provides a simple and intuitive API for handling asynchronous operations
- Includes TypeScript typings for better developer experience
Cons
- May introduce additional complexity for simple use cases
- Requires understanding of Promises and asynchronous programming concepts
- Limited to JavaScript/TypeScript environments
- Might have a slight performance overhead compared to native Promise.all for very simple cases
Code Examples
- Basic usage with a Promise-returning function:
import pMap from 'p-map';
const mapper = async x => {
const result = await someAsyncOperation(x);
return result * 2;
};
const result = await pMap([1, 2, 3], mapper, {concurrency: 2});
console.log(result); // [2, 4, 6]
- Using with async/await and controlling concurrency:
import pMap from 'p-map';
const urls = ['https://example.com', 'https://example.org', 'https://example.net'];
const fetchData = async (url) => {
const response = await fetch(url);
return response.text();
};
const results = await pMap(urls, fetchData, {concurrency: 2});
console.log(results); // Array of fetched HTML content
- Error handling with a custom mapper:
import pMap from 'p-map';
const inputs = [1, 2, 3, 4, 5];
const mapper = async (input) => {
if (input === 3) throw new Error('Invalid input');
return input * 2;
};
try {
const result = await pMap(inputs, mapper, {
concurrency: 2,
stopOnError: false
});
console.log(result); // [2, 4, Error, 8, 10]
} catch (error) {
console.error('An error occurred:', error);
}
Getting Started
To use p-map in your project, first install it via npm:
npm install p-map
Then, import and use it in your JavaScript/TypeScript file:
import pMap from 'p-map';
const mapper = async (item) => {
// Your async operation here
return item * 2;
};
const result = await pMap([1, 2, 3], mapper, {concurrency: 2});
console.log(result);
This example demonstrates basic usage. Adjust the mapper function and options according to your specific use case.
Competitor Comparisons
Async utilities for node and the browser
Pros of async
- More comprehensive with a wide range of utility functions for asynchronous operations
- Well-established and battle-tested library with a large community
- Supports both Node.js and browser environments
Cons of async
- Larger bundle size due to its comprehensive nature
- May have a steeper learning curve for beginners due to its extensive API
- Some users report performance issues with large datasets
Code Comparison
async:
async.map(['file1', 'file2', 'file3'], fs.stat, function(err, results) {
// results is now an array of stats for each file
});
p-map:
import pMap from 'p-map';
const result = await pMap(['file1', 'file2', 'file3'], file => fs.promises.stat(file), {concurrency: 2});
Key Differences
- p-map focuses specifically on mapping operations, while async provides a broader set of utilities
- p-map uses modern JavaScript features like Promises and async/await, making it more aligned with current best practices
- async offers more flexibility in terms of control flow and error handling, but p-map provides a simpler, more focused API
- p-map is generally lighter-weight and may offer better performance for specific use cases, especially with large datasets
Both libraries have their strengths, and the choice between them depends on the specific requirements of your project and your preferred coding style.
:bird: :zap: Bluebird is a full featured promise library with unmatched performance.
Pros of Bluebird
- More comprehensive feature set, including advanced Promise utilities
- Better performance in many scenarios, especially for large-scale applications
- Extensive API with additional methods like
Promise.map
andPromise.reduce
Cons of Bluebird
- Larger package size, which may impact bundle size in browser applications
- Steeper learning curve due to its extensive API and additional features
- Less frequently updated compared to p-map
Code Comparison
p-map:
import pMap from 'p-map';
const result = await pMap(items, async (item) => {
const data = await fetchData(item);
return processData(data);
}, {concurrency: 2});
Bluebird:
const Promise = require('bluebird');
const result = await Promise.map(items, async (item) => {
const data = await fetchData(item);
return processData(data);
}, {concurrency: 2});
Summary
p-map is a lightweight, focused library for mapping over promises with concurrency control. It's ideal for simpler use cases and smaller projects. Bluebird, on the other hand, is a full-featured Promise library with a wide range of utilities, suitable for larger applications with complex asynchronous operations. The choice between them depends on the specific needs of your project, considering factors like bundle size, performance requirements, and the complexity of your asynchronous operations.
A promise library for JavaScript
Pros of Q
- Comprehensive promise library with advanced features like promise chaining and error handling
- Well-established and battle-tested in production environments
- Supports both Node.js and browser environments
Cons of Q
- Larger bundle size compared to more focused libraries
- Steeper learning curve due to its extensive API
- Less actively maintained in recent years
Code Comparison
Q:
Q.all([
fetchUser(),
fetchPosts()
]).then(([user, posts]) => {
console.log(user, posts);
});
p-map:
import pMap from 'p-map';
const result = await pMap(urls, async (url) => {
const response = await fetch(url);
return response.json();
}, {concurrency: 2});
Summary
Q is a full-featured promise library offering a wide range of functionality, while p-map focuses specifically on mapping over promises with concurrency control. Q provides a more comprehensive solution for promise-based programming, but comes with increased complexity and size. p-map, on the other hand, offers a simpler, more targeted approach for concurrent promise mapping, making it easier to use for specific use cases but with fewer overall features compared to Q.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
p-map
Map over promises concurrently
Useful when you need to run promise-returning & async functions multiple times with different inputs concurrently.
This is different from Promise.all()
in that you can control the concurrency and also decide whether or not to stop iterating when there's an error.
Install
npm install p-map
Usage
import pMap from 'p-map';
import got from 'got';
const sites = [
getWebsiteFromUsername('sindresorhus'), //=> Promise
'https://avajs.dev',
'https://github.com'
];
const mapper = async site => {
const {requestUrl} = await got.head(site);
return requestUrl;
};
const result = await pMap(sites, mapper, {concurrency: 2});
console.log(result);
//=> ['https://sindresorhus.com/', 'https://avajs.dev/', 'https://github.com/']
API
pMap(input, mapper, options?)
Returns a Promise
that is fulfilled when all promises in input
and ones returned from mapper
are fulfilled, or rejects if any of the promises reject. The fulfilled value is an Array
of the fulfilled values returned from mapper
in input
order.
pMapIterable(input, mapper, options?)
Returns an async iterable that streams each return value from mapper
in order.
import {pMapIterable} from 'p-map';
// Multiple posts are fetched concurrently, with limited concurrency and backpressure
for await (const post of pMapIterable(postIds, getPostMetadata, {concurrency: 8})) {
console.log(post);
};
input
Type: AsyncIterable<Promise<unknown> | unknown> | Iterable<Promise<unknown> | unknown>
Synchronous or asynchronous iterable that is iterated over concurrently, calling the mapper
function for each element. Each iterated item is await
'd before the mapper
is invoked so the iterable may return a Promise
that resolves to an item.
Asynchronous iterables (different from synchronous iterables that return Promise
that resolves to an item) can be used when the next item may not be ready without waiting for an asynchronous process to complete and/or the end of the iterable may be reached after the asynchronous process completes. For example, reading from a remote queue when the queue has reached empty, or reading lines from a stream.
mapper(element, index)
Type: Function
Expected to return a Promise
or value.
options
Type: object
concurrency
Type: number
(Integer)
Default: Infinity
Minimum: 1
Number of concurrently pending promises returned by mapper
.
backpressure
Only for pMapIterable
Type: number
(Integer)
Default: options.concurrency
Minimum: options.concurrency
Maximum number of promises returned by mapper
that have resolved but not yet collected by the consumer of the async iterable. Calls to mapper
will be limited so that there is never too much backpressure.
Useful whenever you are consuming the iterable slower than what the mapper function can produce concurrently. For example, to avoid making an overwhelming number of HTTP requests if you are saving each of the results to a database.
stopOnError
Only for pMap
Type: boolean
Default: true
When true
, the first mapper rejection will be rejected back to the consumer.
When false
, instead of stopping when a promise rejects, it will wait for all the promises to settle and then reject with an AggregateError
containing all the errors from the rejected promises.
Caveat: When true
, any already-started async mappers will continue to run until they resolve or reject. In the case of infinite concurrency with sync iterables, all mappers are invoked on startup and will continue after the first rejection. Issue #51 can be implemented for abort control.
signal
Only for pMap
Type: AbortSignal
You can abort the promises using AbortController
.
import pMap from 'p-map';
import delay from 'delay';
const abortController = new AbortController();
setTimeout(() => {
abortController.abort();
}, 500);
const mapper = async value => value;
await pMap([delay(1000), delay(1000)], mapper, {signal: abortController.signal});
// Throws AbortError (DOMException) after 500 ms.
pMapSkip
Return this value from a mapper
function to skip including the value in the returned array.
import pMap, {pMapSkip} from 'p-map';
import got from 'got';
const sites = [
getWebsiteFromUsername('sindresorhus'), //=> Promise
'https://avajs.dev',
'https://example.invalid',
'https://github.com'
];
const mapper = async site => {
try {
const {requestUrl} = await got.head(site);
return requestUrl;
} catch {
return pMapSkip;
}
};
const result = await pMap(sites, mapper, {concurrency: 2});
console.log(result);
//=> ['https://sindresorhus.com/', 'https://avajs.dev/', 'https://github.com/']
Related
- p-all - Run promise-returning & async functions concurrently with optional limited concurrency
- p-filter - Filter promises concurrently
- p-times - Run promise-returning & async functions a specific number of times concurrently
- p-props - Like
Promise.all()
but forMap
andObject
- p-map-series - Map over promises serially
- Moreâ¦
Top Related Projects
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot