Convert Figma logo to code with AI

sindresorhus logop-map

Map over promises concurrently

1,272
58
1,272
13

Top Related Projects

28,153

Async utilities for node and the browser

20,444

:bird: :zap: Bluebird is a full featured promise library with unmatched performance.

14,940

A promise library for JavaScript

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

  1. 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]
  1. 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
  1. 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

28,153

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.

20,444

: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 and Promise.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.

14,940

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 Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

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 for Map and Object
  • p-map-series - Map over promises serially
  • More…

NPM DownloadsLast 30 Days