p-map

Map over promises concurrently, with controlled concurrency, backpressure, abort signals, and error aggregation.

Library
npm
v7.1.1
1,517 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
76 /100 Good
Development Activity 84
Maintenance 68
Community 52
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
80 /100 Excellent
Architecture 80
Code Quality 88
Innovation 62
Learning Curve 90

p-map runs an async or sync mapper function over every element of an iterable, awaiting each returned promise while capping how many run at the same time via a concurrency option. It solves the exact gap Promise.all() leaves open: batch operations like paginated API calls, file writes, or database queries need throttling so they don’t overwhelm the target service or run out of memory, but still want to run several in parallel rather than one at a time.

Beyond the core pMap() function, the package exports pMapIterable() for streaming results through an async iterable with independent backpressure control, and pMapSkip — a sentinel a mapper can return to omit an item from the output array without introducing filter-then-map indirection. stopOnError lets callers choose fail-fast semantics or collect every rejection into an AggregateError, and an AbortSignal can cancel in-flight work early. It has no runtime dependencies and ships as a single ESM-only file with full TypeScript types.

What You Get

  • pMap(input, mapper, options) — awaits every element and mapper result while honoring a concurrency cap, returning results in original input order
  • pMapIterable(input, mapper, options) — an async-iterable variant with independent backpressure control for streaming consumption
  • pMapSkip — a sentinel value a mapper can return to exclude an item from the result array
  • stopOnError option — choose fail-fast rejection or continue-and-collect into an AggregateError
  • signal option — cancel in-flight mapping early via a standard AbortController/AbortSignal
  • Support for both synchronous and asynchronous iterables, including iterables whose items are themselves promises

Common Use Cases

  • Fetching or posting to a rate-limited third-party API across a list of IDs without tripping its concurrency or rate limits
  • Resizing, uploading, or transforming a batch of files in parallel while capping concurrent file-handle or memory usage
  • Running database reads/writes across many rows without exhausting a connection pool
  • Streaming large or slow-arriving datasets through pMapIterable so a consumer can process results as they complete rather than waiting for the whole batch
  • Filtering a collection while mapping in one pass using pMapSkip, avoiding a separate .filter() step

Under The Hood

Architecture

p-map exposes three named exports from a single index.js: the promise-returning pMap, the async-generator pMapIterable, and the pMapSkip sentinel symbol. pMap wraps its whole body in a new Promise executor and drives concurrency with a hand-rolled scheduler — a recursive, self-invoking next() that pulls from the shared iterator, launches a detached async IIFE per slot, and decrements/increments a resolvingCount counter to know when the iterable is exhausted and every in-flight mapper has settled. pMapIterable takes a different shape suited to streaming: it keeps a promises array acting as an ordered queue, a trySpawn() function that launches new mapper calls whenever both the concurrency and backpressure ceilings allow it, and yields results by awaiting the head of the queue in a while loop, converting mapper errors into thrown values inside the generator rather than rejecting an unhandled promise. Both paths validate their inputs (iterable-ness, mapper type, integer concurrency) before doing any work, and pMap wires an AbortSignal listener with an explicit cleanup() step so the listener doesn’t leak past resolution.

Tech Stack

The package is pure, dependency-free ES2022+ JavaScript distributed as native ESM ("type": "module", exports.default) with hand-written index.d.ts type declarations rather than generated ones, targeting Node.js 18+ per engines. There is no build step — index.js ships as-authored. Tooling is entirely dev-side: xo (an opinionated ESLint config) for linting, ava as the test runner, and tsd for asserting the .d.ts file’s type signatures compile and infer correctly, all wired through a single npm test script and a GitHub Actions workflow.

Code Quality

test.js is extensive — several hundred lines covering concurrency ordering, stopOnError true/false branches, AggregateError shape, abort-signal cancellation, pMapSkip (including multiple skips in one run), and both sync and async iterables, using ava with delay/time-span/random-int helpers to assert timing-sensitive concurrency behavior rather than just final output. A separate test-multiple-pmapskips-performance.js guards against an accidental quadratic path when many skips occur. Error handling is explicit throughout — thrown TypeErrors for invalid input shapes, careful distinction between stopOnError: true (immediate reject) and false (collect into AggregateError) — and the .d.ts file’s inferred types are checked at build time via tsd, giving the library both automated type-safety and behavioral test coverage despite its small surface area.

What Makes It Unique

p-map’s distinguishing choice is offering two complementary concurrency models rather than one: a batch-oriented pMap that resolves to a single ordered array, and a separately-tunable pMapIterable whose backpressure option decouples “how many mappers run at once” from “how many completed-but-unconsumed results may pile up” — letting a slow consumer avoid runaway memory growth from a fast producer. Combined with pMapSkip for inline filtering and native AbortSignal support, it covers concurrency-control patterns that competing single-function libraries typically split across several packages, while still shipping as one small, dependency-free file.

Used by 17 apps in this directory

JavaScript
64%
AGPL 3.0

overleaf

Collaboration · Productivity

18,266

Open-source, real-time collaborative LaTeX editor with sandboxed compilation and full TeXLive support for self-hosted academic and research teams.

View details
84
Repo Health
80
Technical
59
Dependency
Built with
JavaScript 64%
TypeScript 30%
Updated 1 months ago
TypeScript
100%
AGPL 3.0

RSSHub

Automation · Social Media

46,631

Turn any website into an RSS feed — social media, streaming platforms, and niche sites all become subscribable in seconds.

View details
94
Repo Health
82
Technical
71
Dependency
Built with
TypeScript 100%
Updated yesterday
TypeScript
99%
MIT

Rudel

Developer Tools

306

Open-source analytics for Claude Code and Codex sessions — a CLI uploads session transcripts to a self-hostable dashboard tracking token usage, session duration, activity patterns, and model usage.

View details
75
Repo Health
67
Technical
71
Dependency
Built with
TypeScript 99%
Updated 1 weeks ago
TypeScript
99%
MIT

Sanity

CMS

6,370

Open-source headless CMS with a fully customizable React Studio, real-time collaborative editing, structured content modeling, and GROQ query language

View details
92
Repo Health
90
Technical
66
Dependency
Built with
TypeScript 99%
Updated yesterday
TypeScript
89%
Other

strapi

CMS

73,368

Open-source headless CMS that auto-generates REST and GraphQL APIs from your content models, with a fully customizable admin panel you control.

View details
93
Repo Health
84
Technical
63
Dependency
Built with
TypeScript 89%
JavaScript 11%
Updated 2 days ago
TypeScript
98%
Apache 2.0

Tianji

Analytics · Monitoring

3,119

Replace Google Analytics, UptimeKuma, and Prometheus with one self-hosted platform that tracks websites, monitors uptime, and reports server health.

View details
86
Repo Health
76
Technical
64
Dependency
Built with
TypeScript 98%
Updated 2 days ago
TypeScript
99%
Apache 2.0

Trigger.dev

AI Development · Automation · Developer Tools

16,606

Build and deploy fully-managed AI agents and background jobs in TypeScript — with no timeouts, durable retries, real-time observability, and elastic scaling built in.

View details
90
Repo Health
9
Technical
63
Dependency
Built with
TypeScript 99%
Updated yesterday
TypeScript
87%
Other

Webiny JS

Blogging · CMS · Ecommerce

8,047

Open-source, self-hosted CMS on AWS serverless — a TypeScript framework you extend with code, not a product you configure through a UI.

View details
90
Repo Health
86
Technical
61
Dependency
Built with
TypeScript 87%
JavaScript 12%
Updated 2 days ago

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers