Baike.dev
All toolsOnline toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
C

contra

> 编程语言
Open source

:surfer: Asynchronous flow control with a functional taste to it

777 stars0 likes4 views
WebsiteGitHub

About

:surfer: Asynchronous flow control with a functional taste to it

![contra.png][logo]

Asynchronous flow control with a functional taste to it

λ aims to stay small and simple, while powerful. Inspired by [async][1] and [lodash][2]. Methods are implemented individually and not as part of a whole. That design helps when considering to export functions individually. If you need all the methods in async, then stick with it. Otherwise, you might want to check λ out!

Feature requests will be considered on a case-by-case basis.

Quick Links

  • CHANGELOG
  • Comparison with async
  • Browser Support
  • License

API

Flow Control

  • λ.waterfall
  • λ.series
  • λ.concurrent

Functional

  • λ.each
  • λ.each.series
  • λ.map
  • λ.map.series
  • λ.filter
  • λ.filter.series

Uncategorized

  • λ.queue
  • λ.emitter
  • λ.curry

Install

Install using npm or bower. Or get the [source code][3] and embed that in a `


The only reason `contra` isn't published as `λ` directly is to make it easier for you to type.

[_Back to top_](#quick-links)

# API

These are the asynchronous flow control methods provided by `λ`.

## `λ.waterfall(tasks, done?)`

Executes tasks in series. Each step receives the arguments from the previous step.

- `tasks` Array of functions with the `(...results, next)` signature
- `done` Optional function with the `(err, ...results)` signature

```js
λ.waterfall([
  function (next) {
    next(null, 'params for', 'next', 'step');
  },
  function (a, b, c, next) {
    console.log(b);
    // [_Back to top_](#quick-links)

## `λ.concurrent(tasks, cap?, done?)`

Executes tasks concurrently. Results get passed as an array or hash to an optional `done` callback. Task order is preserved in results. You can set a concurrency cap, and it's uncapped by default.

- `tasks` Collection of functions with the `(cb)` signature. Can be an array or an object
- `cap` Optional concurrency level, used by the internal [queue](#%CE%BBqueueworker-cap1)
- `done` Optional function with the `(err, results)` signature

…

js
λ.series([
  function (next) {
    setTimeout(function () {
      next(null, 'boom');
    }, 1000);
  },
  function (next) {
    next(null, 'foo');
  }
], function (err, results) {
  console.log(results);
  // [_Back to top_](#quick-links)

## `λ.each(items, cap?, iterator, done?)`

Applies an iterator to each element in the collection concurrently.

- `items` Collection of items. Can be an array or an object
- `cap` Optional concurrency level, used by the internal [queue](#%CE%BBqueueworker-cap1)
- `iterator(item, key?, cb)` Function to execute on each item
  - `item` The current item
  - `key` Optional, array/object key of the current item
  - `cb` Needs to be called when processing for current item is done
- `done` Optional function with the `(err)` signature

…

js
λ.map({ thing: 900, another: 23 }, function (item, cb) {
  setTimeout(function () {
    cb(null, item * 2);
  }, item);
}, function (err, results) {
  console.log(results);
  [_Back to top_](#quick-links)

## `λ.map.series(items, iterator, done?)`

Effectively an alias for `λ.map(items, 1, iterator, done?)`.

[_Back to top_](#quick-links)

## `λ.filter(items, cap?, iterator, done?)`

Applies an iterator to each element in the collection concurrently. Produces an object with the filtered results. Task order is preserved in results.

- `items` Collection of items. Can be an array or an object
- `cap` Optional concurrency level, used by the internal [queue](#%CE%BBqueueworker-cap1)
- `iterator(item, key?, cb)` Function to execute on each item
  - `item` The current item
  - `key` Optional, array/object key of the current item
  - `cb` Needs to be called when processing for current item is done
    - `err` An optional error which will short-circuit the filtering process, calling `done`
    - `keep` Truthy will keep the item. Falsy will remove it in the results
- `done` Optional function with the `(err, results)` signature

…

js
var q = λ.queue(worker);

function worker (job, done) {
  console.log(job);
  done(null);
}

q.push('job', function () {
  console.log('this job is done!');
});

q.push(['some', 'more'], function () {
  console.log('one of these jobs is done!');
});

q.on('drain', function () {
  console.log('all done!');
  // if you enqueue more tasks now, then drain
  // will fire again when pending.length reaches 0
});

// [_Back to top_](#quick-links)

## `λ.emitter(thing={}, options={})`

Augments `thing` with the event emitter methods listed below. If `thing` isn't provided, an event emitter is created for you. Emitter methods return the `thing` for chaining.

- `thing` Optional. Writable JavaScript object
- `emit(type, ...arguments)` Emits an event of type `type`, passing any `...arguments`
- `emitterSnapshot(type)` Returns a function you can call, passing any `...arguments`
- `on(type, fn)` Registers an event listener `fn` for `type` events
- `once(type, fn)` Same as `on`, but the listener is discarded after one callback
- `off(type, fn)` Unregisters an event listener `fn` from `type` events
- `off(type)` Unregisters all event listeners from `type` events
- `off()` Unregisters all event listeners

The `emitterSnapshot(type)` method lets you remove all event listeners before emitting an event that might add more event listeners which shouldn't be removed. In the example below, `thing` removes all events and then emits a `'destroy'` event, resulting in a `'create'` event handler being attached. If we just used `thing.off()` after emitting the destroy event, the `'create'` event handler would be wiped out too _(or the consumer would have to know implementation details as to avoid this issue)_.

```js
var thing = λ.emitter();

thing.on('foo', foo);
thing.on('bar', bar);
thing.on('destroy', function () {
  thing.on('create', reinitialize);
});

var destroy = thing.emitterSnapshot('destroy');
thing.off();
destroy();

The emitter can be configured with the following options, too.

  • async Debounce listeners asynchronously. By default they're executed in sequence.
  • throws Throw an exception if an error event is emitted and no listeners are defined. Defaults to true.
javascript
var thing = λ.emitter(); // also, λ.emitter({ foo: 'bar' })

thing.once('something', function (level) {
  console.log('something FIRST TROLL');
});

thing.on('something', function (level) {
  console.log('something level ' + level);
});

thing.emit('something', 4);
thing.emit('something', 5);
// [_Back to top_](#quick-links)

## `λ.curry(fn, ...arguments)`

Returns a function bound with some arguments and a `next` callback.

```js
λ.curry(fn, 1, 3, 5);
// [_Back to top_](#quick-links)

# Comparison with `async`

[`async`][1]|`λ`
---|---
Aimed at Noders|Tailored for browsers
Arrays for [some][5], collections for [others][6]|Collections for **everyone**!
`apply`|`curry`
`parallel`|`concurrent`
`parallelLimit`|`concurrent`
`mapSeries`|`map.series`
More _comprehensive_|More _focused_
`~29.6k (minified, uncompressed)`|`~2.7k (minified, uncompressed)`

`λ` isn't meant to be a replacement for `async`. It aims to provide a more focused library, and a bit more consistency.

[_Back to top_](#quick-links)

# Browser Support
If you need support for one of the legacy browsers listed below, you'll need `contra.shim.js`.

- IE [_Back to top_](#quick-links)

# License

MIT

[_Back to top_](#quick-links)

  [logo]: https://raw.github.com/bevacqua/contra/master/resources/contra.png
  [1]: https://github.com/caolan/async
  [2]: https://github.com/lodash/lodash
  [3]: https://github.com/bevacqua/contra/tree/master/src/contra.js
  [4]: https://github.com/bevacqua
  [5]: https://github.com/caolan/async#maparr-iterator-callback
  [6]: https://github.com/caolan/async#paralleltasks-callback

Issues· 1 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

JavaScript

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言