async

Higher-order async utility functions for callback, async/await, and promise-based control flow in Node.js and the browser.

Library
npm
v3.2.6
28,119 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
82 /100 Excellent
Development Activity 80
Maintenance 64
Community 84
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
77 /100 Good
Architecture 80
Code Quality 76
Innovation 66
Learning Curve 85

Async is a widely-used JavaScript utility library providing around 70 functions for managing asynchronous control flow: collection iteration (each, map, filter, reduce, sortBy), control-flow composition (waterfall, series, parallel, auto), and concurrency utilities (queue, cargo, retry). Every function follows Node’s error-first callback convention while also transparently accepting native async functions and Promise-returning functions, and returns a Promise when no callback is supplied.

Originally created in 2010, before Promises or async/await existed in JavaScript, Async remains one of the most depended-upon packages in the npm ecosystem, still receiving maintenance and pulling over 100 million weekly downloads. Version 3 rewrote the internals as ES modules with full async-function support while preserving the same callback-first API that made it a de facto standard for pre-Promise Node.js code.

What You Get

  • Around 70 async utility functions covering collections (each, map, filter, reduce, sortBy), control flow (series, parallel, waterfall, auto, race), and utilities (queue, cargo, retry, memoize)
  • Uniform support for three calling conventions — Node-style error-first callbacks, native async/await functions, and Promises — mixed freely within the same call
  • A dependency-graph task runner (auto/autoInject) that resolves execution order and concurrency automatically from named task requirements
  • Bounded-concurrency primitives (queue, cargo, and *Limit variants) for throttling parallel work against rate limits or resource constraints
  • Both a CommonJS build and a native ESM build (plus the separate async-es package), so the same API works in Node, bundlers, and directly in the browser

Common Use Cases

  • Rate-limiting concurrent API calls with mapLimit/queue so a batch job doesn’t overwhelm a downstream service
  • Orchestrating a multi-step startup sequence with auto, where some steps depend on the results of others finishing first
  • Migrating or maintaining legacy Node.js callback-based codebases without rewriting call sites to promises
  • Iterating over large collections asynchronously with eachSeries/mapSeries when operations must run in strict order, such as sequential file writes

Under The Hood

Architecture

Async’s roughly 5,500 lines under lib/ are organized one function per file (lib/auto.js, lib/queue.js, lib/waterfall.js, and so on), each a thin wrapper around shared primitives in lib/internal/: DoublyLinkedList.js backs the queue’s task list, wrapAsync.js/asyncify.js normalize callback-, async-function-, and Promise-returning iteratees into one internal calling convention, and eachOfLimit.js/parallel.js implement the concurrency-limited iteration loop that most collection functions delegate to. lib/index.js re-exports every public function. The dependency-graph runner in auto.js builds an adjacency structure over the tasks object and drives each task’s callback through once()/onlyOnce() guards, starting a task only once all its listed dependencies have resolved. Because nearly every public function is a shim over the same wrapAsync/eachOfLimit internals, a change to the calling-convention normalization or the queue’s internal linked-list would ripple through virtually the entire public API.

Tech Stack

The package ships with zero runtime dependencies — a deliberate choice for a foundational utility library — and relies on Babel (preset-es2015/es2017) to transpile the ES-module source under lib/ into the CommonJS dist/async.js published to npm, alongside a separate async-es package for pure-ESM consumers; Rollup produces the browser bundle. Testing runs on Mocha with Chai assertions and nyc coverage in Node, plus a parallel browser pass via Karma (karma-browserify, karma-firefox-launcher, karma-safari-launcher) exercising the same suite in real browsers. ESLint with @babel/eslint-parser enforces style, and GitHub Actions CI runs lint followed by the full test matrix on every push, with Coveralls tracking coverage. Documentation is generated via JSDoc from inline @name/@category annotations in each lib file.

Code Quality

The test/ directory mirrors lib/ almost one-to-one, with dozens of individual test cases per function covering callback-style, async-function, and Promise-based invocation paths plus explicit error-propagation and double-callback edge cases. Error handling is explicit throughout: internal helpers like once.js and onlyOnce.js exist specifically to guard against a callback being invoked twice, and wrapAsync.js/asyncify.js branch explicitly on whether a passed function is a plain callback function, an AsyncFunction, or an async generator rather than silently coercing mismatches. There is no static type system — plain ES modules, no TypeScript — but ESLint enforces consistent style, and CI runs the full Node and browser test suites on every push.

API Design Async’s defining design choice is accepting three different calling conventions — error-first callbacks, native async functions, and Promise-returning functions — through every one of its roughly 70 functions via the wrapAsync/asyncify normalization layer, and returning a Promise itself when no callback is supplied. Function naming is highly consistent: a base verb (each, map, filter, sortBy) composes with Series (strict sequential) and Limit (bounded concurrency) suffixes, so learning one function’s variants teaches the pattern for the rest of the library. This uniformity is also the biggest cost for newcomers today: because the library predates Promises and async/await in the language, much of its surface area (waterfall, auto, series) now solves a problem the language itself later absorbed. Documentation stays thorough regardless — a JSDoc-generated per-function reference plus inline @example blocks in every source file keep the boilerplate for adopting any single function low.

Used by 23 apps in this directory

JavaScript
65%
Other

GDevelop

Design Tools · Developer Tools · Game Development

27,329

No-code, open-source game engine for building 2D, 3D and multiplayer games — publish to iOS, Android, Steam and the web.

View details
93
Repo Health
82
Technical
61
Dependency
Built with
JavaScript 65%
C++ 22%
TypeScript 11%
Updated 2 weeks ago
TypeScript
98%
Other

GrowthBook

Ab Testing Experimentation · Analytics · Developer Tools

8,485

Open source feature flags, A/B testing, and warehouse-native experimentation that queries your existing data infrastructure—no data movement required.

View details
92
Repo Health
85
Technical
63
Dependency
Built with
TypeScript 98%
Updated 2 weeks ago
TypeScript
98%
Other

Kibana

Analytics · Monitoring

21,308

Your open source window into the Elastic Stack — query, visualize, and act on data stored in Elasticsearch with real-time dashboards, AI-assisted search, and automated alerting.

View details
98
Repo Health
87
Technical
62
Dependency
Built with
TypeScript 98%
Updated 1 weeks ago
JavaScript
88%
GPL 3.0

NodeBB

Community

15,232

Modern Node.js forum software with real-time WebSockets, multi-database support, and a plugin ecosystem — the community platform built for the open web and the Fediverse.

View details
97
Repo Health
78
Technical
70
Dependency
Built with
JavaScript 88%
Go Template 11%
Updated 2 weeks ago
TypeScript
98%
Other

Novu

Developer Tools

40,131

Open-source communication infrastructure that connects your products and AI agents to every channel your users live on — Inbox, Email, SMS, Push, Chat, and more.

View details
93
Repo Health
80
Technical
64
Dependency
Built with
TypeScript 98%
Updated 1 weeks ago
Python
37%
Other

Open WebUI

AI Agents · AI Assistants

154,169

The extensible, privacy-first AI platform that runs Ollama, OpenAI, and any LLM backend behind a polished, feature-packed web interface.

View details
92
Repo Health
75
Technical
66
Dependency
Built with
Python 37%
Svelte 34%
JavaScript 21%
Updated 2 weeks ago
JavaScript
64%
AGPL 3.0

overleaf

Collaboration · Productivity

18,220

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

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

PeerTube

Social Media

15,350

A federated, ActivityPub-based video hosting platform built by Framasoft — self-hostable instances interconnect into a network with no vendor lock-in, P2P-assisted streaming, and no ads.

View details
96
Repo Health
75
Technical
67
Dependency
Built with
TypeScript 91%
Updated 2 weeks ago
Python
49%
Other

Arize Phoenix

Analytics · Devops · Monitoring

11,770

Open-source AI observability platform for tracing, evaluating, and debugging LLM applications with built-in intelligence and MCP support.

View details
92
Repo Health
88
Technical
67
Dependency
Built with
Python 49%
TypeScript 43%
Updated 1 weeks 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