Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/metarhia/metasync
Asynchronous Programming Library for JavaScript & Node.js
https://github.com/metarhia/metasync
array async asynchronous callback chain collector composition impress javascript js metarhia node nodejs parallel promise series sync synchronous thenable
Last synced: 5 days ago
JSON representation
Asynchronous Programming Library for JavaScript & Node.js
- Host: GitHub
- URL: https://github.com/metarhia/metasync
- Owner: metarhia
- License: mit
- Created: 2016-07-18T18:44:42.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2024-03-20T06:32:17.000Z (10 months ago)
- Last Synced: 2025-01-11T23:10:21.098Z (12 days ago)
- Topics: array, async, asynchronous, callback, chain, collector, composition, impress, javascript, js, metarhia, node, nodejs, parallel, promise, series, sync, synchronous, thenable
- Language: JavaScript
- Homepage: https://metarhia.com
- Size: 1.19 MB
- Stars: 205
- Watchers: 24
- Forks: 35
- Open Issues: 45
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Authors: AUTHORS
Awesome Lists containing this project
README
# Asynchronous Programming Library
[![ci status](https://github.com/metarhia/metasync/workflows/Testing%20CI/badge.svg)](https://github.com/metarhia/metasync/actions?query=workflow%3A%22Testing+CI%22+branch%3Amaster)
[![snyk](https://snyk.io/test/github/metarhia/metasync/badge.svg)](https://snyk.io/test/github/metarhia/metasync)
[![npm version](https://badge.fury.io/js/metasync.svg)](https://badge.fury.io/js/metasync)
[![npm downloads/month](https://img.shields.io/npm/dm/metasync.svg)](https://www.npmjs.com/package/metasync)
[![npm downloads](https://img.shields.io/npm/dt/metasync.svg)](https://www.npmjs.com/package/metasync)
[![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/metarhia/metasync/blob/master/LICENSE)## Installation
```bash
$ npm install metasync
```## Asynchronous functions composition
`metasync(fns)(data, done)`
- `fns` - array of callback-last functions, callback contranct err-first
- `data` - input data (optional)
- `done` - err-first callback
- Returns: composed callback-last / err-first function![composition](https://cloud.githubusercontent.com/assets/4405297/16968374/1b81f160-4e17-11e6-96fa-9d7e2b422396.png)
```js
const composed = metasync([f1, f2, f3, [[f4, f5, [f6, f7], f8]], f9]);
```- Array of functions gives sequential execution: `[f1, f2, f3]`
- Double brackets array of functions gives parallel execution: `[[f1, f2, f3]]`_Example:_
```js
const metasync = require('metasync');
const fs = require('fs');// Data collector (collect keys by count)
const dc = metasync.collect(4);dc.pick('user', { name: 'Marcus Aurelius' });
fs.readFile('HISTORY.md', (err, data) => dc.collect('history', err, data));
dc.take('readme', fs.readFile, 'README.md');
setTimeout(() => dc.pick('timer', { date: new Date() }), 1000);// Key collector (collect certain keys by names)
const kc = metasync
.collect(['user', 'history', 'readme', 'timer'])
.timeout(2000)
.distinct()
.done((err, data) => console.log(data));kc.pick('user', { name: 'Marcus Aurelius' });
kc.take('history', fs.readFile, 'HISTORY.md');
kc.take('readme', fs.readFile, 'README.md');
setTimeout(() => kc.pick('timer', { date: new Date() }), 1000);
```## API
### callbackify(fn)
- `fn`: [``][function] promise-returning function
_Returns:_ [``][function]
Convert Promise-returning to callback-last / error-first contract
### asyncify(fn)
- `fn`: [``][function] regular synchronous function
_Returns:_ [``][function] with contract: callback-last / error-first
Convert sync function to callback-last / error-first contract
### promiseToCallbackLast(promise, callback)
- `promise`: [``][promise]
- `callback`: [``][function]Convert Promise to callback-last
### promisify(fn)
- `fn`: [``][function] callback-last function
_Returns:_ [``][function] Promise-returning function
Convert async function to Promise-returning function
### promisifySync(fn)
- `fn`: [``][function] regular synchronous function
_Returns:_ [``][function] Promise-returning function
Convert sync function to Promise object
### map(items, fn, done)
- `items`: [``][array] incoming
- `fn`: [``][function] to be executed for each value in the array
- `current`: `` current element being processed in the array
- `callback`: [``][function]
- `err`: [``][error]|[``][null]
- `value`: ``
- `done`: [``][function] on done
- `err`: [``][error]|[``][null]
- `result`: [``][array]Asynchronous map (iterate parallel)
### filter(items, fn, done)
- `items`: [``][array] incoming
- `fn`: [``][function] to be executed for each value in the array
- `value`: `` item from items array
- `callback`: [``][function]
- `err`: [``][error]|[``][null]
- `accepted`: [``][boolean]
- `done`: [``][function] on done
- `err`: [``][error]|[``][null]
- `result`: [``][array]Asynchrous filter (iterate parallel)
_Example:_
```js
metasync.filter(
['data', 'to', 'filter'],
(item, callback) => callback(item.length > 2),
(err, result) => console.dir(result),
);
```### reduce(items, fn, done\[, initial\])
- `items`: [``][array] incoming
- `fn`: [``][function] to be executed for each value in array
- `previous`: `` value previously returned in the last iteration
- `current`: `` current element being processed in the array
- `callback`: [``][function] callback for returning value back to
reduce function
- `err`: [``][error]|[``][null]
- `data`: `` resulting value
- `counter`: [``][number] index of the current element being processed
in array
- `items`: [``][array] the array reduce was called upon
- `done`: [``][function] on done
- `err`: [``][error]|[``][null]
- `result`: [``][array]
- `initial`: `` optional value to be used as first argument in first
iterationAsynchronous reduce
### reduceRight(items, fn, done\[, initial\])
- `items`: [``][array] incoming
- `fn`: [``][function] to be executed for each value in array
- `previous`: `` value previously returned in the last iteration
- `current`: `` current element being processed in the array
- `callback`: [``][function] callback for returning value back to
reduce function
- `err`: [``][error]|[``][null]
- `data`: `` resulting value
- `counter`: [``][number] index of the current element being processed
in array
- `items`: [``][array] the array reduce was called upon
- `done`: [``][function] on done
- `err`: [``][error]|[``][null]
- `result`: [``][array]
- `initial`: `` optional value to be used as first argument in first
iterationAsynchronous reduceRight
### each(items, fn, done)
- `items`: [``][array] incoming
- `fn`: [``][function]
- `value`: `` item from items array
- `callback`: [``][function]
- `err`: [``][error]|[``][null]
- `done`: [``][function] on done
- `err`: [``][error]|[``][null]
- `items`: [``][array]Asynchronous each (iterate in parallel)
_Example:_
```js
metasync.each(
['a', 'b', 'c'],
(item, callback) => {
console.dir({ each: item });
callback();
},
(err, data) => console.dir('each done'),
);
```### series(items, fn, done)
- `items`: [``][array] incoming
- `fn`: [``][function]
- `value`: `` item from items array
- `callback`: [``][function]
- `err`: [``][error]|[``][null]
- `done`: [``][function] on done
- `err`: [``][error]|[``][null]
- `items`: [``][array]Asynchronous series
_Example:_
```js
metasync.series(
['a', 'b', 'c'],
(item, callback) => {
console.dir({ series: item });
callback();
},
(err, data) => {
console.dir('series done');
},
);
```### find(items, fn, done)
- `items`: [``][array] incoming
- `fn`: [``][function]
- `value`: `` item from items array
- `callback`: [``][function]
- `err`: [``][error]|[``][null]
- `accepted`: [``][boolean]
- `done`: [``][function] on done
- `err`: [``][error]|[``][null]
- `result`: ``Asynchronous find (iterate in series)
_Example:_
```js
metasync.find(
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
(item, callback) => callback(null, item % 3 === 0 && item % 5 === 0),
(err, result) => {
console.dir(result);
},
);
```### every(items, fn, done)
- `items`: [``][array] incoming
- `fn`: [``][function]
- `value`: `` item from items array
- `callback`: [``][function]
- `err`: [``][error]|[``][null]
- `accepted`: [``][boolean]
- `done`: [``][function] on done
- `err`: [``][error]|[``][null]
- `result`: [``][boolean]Asynchronous every
### some(items, fn, done)
- `items`: [``][array] incoming
- `fn`: [``][function]
- `value`: `` item from items array
- `callback`: [``][function]
- `err`: [``][error]|[``][null]
- `accepted`: [``][boolean]
- `done`: [``][function] on done
- `err`: [``][error]|[``][null]
- `result`: [``][boolean]Asynchronous some (iterate in series)
### asyncMap(items, fn\[, options\]\[, done\])
- `items`: [``][array] incoming dataset
- `fn`: [``][function]
- `item`: ``
- `index`: [``][number]
- `options`: [``][object] map params, optional
- `min`: [``][number] min number of items in one next call
- `percent`: [``][number] ratio of map time to all time
- `done`: [``][function] call on done, optional
- `err`: [``][error]|[``][null]
- `result`: [``][array]Non-blocking synchronous map
### asyncIter(base)
- `base`: [``][iterable]|[``][asynciterable] an
iterable that is wrapped in [``][asynciterator]_Returns:_ [``][asynciterator]
Create an AsyncIterator instance
### class AsyncIterator
#### AsyncIterator.prototype.constructor(base)
#### async AsyncIterator.prototype.next()
#### async AsyncIterator.prototype.count()
#### async AsyncIterator.prototype.each(fn, thisArg)
#### async AsyncIterator.prototype.forEach(fn, thisArg)
#### async AsyncIterator.prototype.parallel(fn, thisArg)
#### async AsyncIterator.prototype.every(predicate, thisArg)
#### async AsyncIterator.prototype.find(predicate, thisArg)
#### async AsyncIterator.prototype.includes(element)
#### async AsyncIterator.prototype.reduce(reducer, initialValue)
#### async AsyncIterator.prototype.some(predicate, thisArg)
#### async AsyncIterator.prototype.someCount(predicate, count, thisArg)
#### async AsyncIterator.prototype.collectTo(CollectionClass)
#### async AsyncIterator.prototype.collectWith(obj, collector)
#### async AsyncIterator.prototype.join(sep = ', ', prefix = '', suffix = '')
#### async AsyncIterator.prototype.toArray()
#### AsyncIterator.prototype.map(mapper, thisArg)
#### AsyncIterator.prototype.filter(predicate, thisArg)
#### AsyncIterator.prototype.flat(depth = 1)
#### AsyncIterator.prototype.flatMap(mapper, thisArg)
#### AsyncIterator.prototype.zip(...iterators)
#### AsyncIterator.prototype.chain(...iterators)
#### AsyncIterator.prototype.take(amount)
#### AsyncIterator.prototype.takeWhile(predicate, thisArg)
#### AsyncIterator.prototype.skip(amount)
#### AsyncIterator.prototype.throttle(percent, min)
#### AsyncIterator.prototype.enumerate()
### collect(expected)
- `expected`: [``][number]|[``][string]
_Returns:_ [``][collector]
Create Collector instance
### class Collector
Data collector
#### Collector.prototype.constructor(expected)
- `expected`: [``][number]|[``][string] count or keys
Data collector
#### Collector.prototype.collect(key, err, value)
- `key`: [``][string]
- `err`: [``][error]
- `value`: ``_Returns:_ [``][this]
Pick or fail key
#### Collector.prototype.pick(key, value)
- `key`: [``][string]
- `value`: ``_Returns:_ [``][this]
Pick key
#### Collector.prototype.fail(key, err)
- `key`: [``][string]
- `err`: [``][error]_Returns:_ [``][this]
Fail key
#### Collector.prototype.take(key, fn, args)
- `key`: [``][string]
- `fn`: [``][function]
- `args`: [``][array] rest arguments, to be passed in fn_Returns:_ [``][this]
Take method result
#### Collector.prototype.timeout(msec)
- `msec`: [``][number]
_Returns:_ [``][this]
Set timeout
#### Collector.prototype.done(callback)
- `callback`: [``][function]
- `err`: [``][error]
- `data`: ``_Returns:_ [``][this]
Set on done listener
#### Collector.prototype.finalize(key, err, data)
#### Collector.prototype.distinct(value)
- `value`: [``][boolean]
_Returns:_ [``][this]
Deny or allow unlisted keys
#### Collector.prototype.cancel(err)
#### Collector.prototype.then(fulfill, reject)
### compose(flow)
- `flow`: [``][function] callback-last / err-first
_Returns:_ [``][function] composed callback-last / err-first
Asynchronous functions composition
Array of functions results in sequential execution: `[f1, f2, f3]` Double
brackets array of functions results in parallel execution: `[[f1, f2, f3]]`_Example:_
```js
const composed = metasync([f1, f2, f3, [[f4, f5, [f6, f7], f8]], f9]);
```### class Composition
#### Composition.prototype.constructor()
#### Composition.prototype.on(name, callback)
#### Composition.prototype.finalize(err)
#### Composition.prototype.collect(err, result)
#### Composition.prototype.parallel()
#### Composition.prototype.sequential()
#### Composition.prototype.then(fulfill, reject)
#### Composition.prototype.clone()
Clone composed
#### Composition.prototype.pause()
Pause execution
#### Composition.prototype.resume()
Resume execution
#### Composition.prototype.timeout(msec)
- `msec`: [``][number]
Set timeout
#### Composition.prototype.cancel()
Cancel execution where possible
### firstOf(fns, callback)
- `fns`: [``][function] callback-last / err-first
- `callback`: [``][function] on done, err-firstExecutes all asynchronous functions and pass first result to callback
### parallel(fns\[, context\], callback)
- `fns`: [``][function] callback-last / err-first
- `context`: [``][object] incoming data, optional
- `callback`: [``][function] on done, err-firstParallel execution
_Example:_
```js
metasync.parallel([f1, f2, f3], (err, data) => {});
```### sequential(fns\[, context\], callback)
- `fns`: [``][function] callback-last with err-first contract
- `context`: [``][object] incoming data, optional
- `callback`: [``][function] err-first on doneSequential execution
_Example:_
```js
metasync.sequential([f1, f2, f3], (err, data) => {});
```### runIf(condition\[, defaultVal\], asyncFn, ...args)
- `condition`: ``
- `defaultVal`: `` optional, value that will be returned to callback if
`condition` is falsy.
- `asyncFn`: [``][function] callback-last function that will be
executed if `condition` if truthy
- `args`: `` args to pass to `asyncFn`Run `asyncFn` if `condition` is truthy, else return `defaultVal` to callback.
### runIfFn(asyncFn, ...args)
- `asyncFn`: [``][function] callback-last function that will be
executed if it is provided
- `args`: `` args to pass to `asyncFn`Run `asyncFn` if it is provided
### class do
#### do.prototype.constructor(fn, ...args)
### toAsync(fn)
- `fn`: [``][function] callback-last / err-first
_Returns:_ [``][function]
Convert synchronous function to asynchronous
Transform function with args arguments and callback to function with args as
separate values and callback### asAsync(fn, args)
- `fn`: [``][function] asynchronous
- `args`: [``][array] its argumentsWrap function adding async chain methods
### of(args)
- `args`: [``][array]
Applicative f => a -> f a
### concat(fn1, fn2)
- `fn1`: [``][function]
- `fn2`: [``][function]Monoid m => a -> a -> a
### fmap(fn1, f)
- `fn1`: [``][function]
- `f`: [``][function]Functor f => (a -> b) -> f a -> f b
### ap(fn, funcA)
- `fn`: [``][function]
- `funcA`: [``][function]Applicative f => f (a -> b) -> f a -> f b
### memoize(fn)
- `fn`: [``][function] sync or async
_Returns:_ [``][function] memoized
Create memoized function
### class Memoized
#### Memoized.prototype.constructor()
#### Memoized.prototype.clear()
#### Memoized.prototype.add(key, err, data)
#### Memoized.prototype.del(key)
#### Memoized.prototype.get(key, callback)
#### Memoized.prototype.on(eventName, listener)
- `eventName`: [``][string]
- `listener`: [``][function] handlerAdd event listener
_Example:_
```js
const memoized = new Memoized();
memoized.on('memoize', (err, data) => { ... });
memoized.on('add', (key, err, data) => { ... });
memoized.on('del', (key) => { ... })
memoized.on('clear', () => { ... });
```#### Memoized.prototype.emit(eventName, args)
- `eventName`: [``][string]
- `args`: `` rest argumentsEmit Memoized events
### poolify(factory, min, norm, max)
### queue(concurrency)
- `concurrency`: [``][number] simultaneous and asynchronously executing
tasks_Returns:_ [``][queue]
Create Queue instance
### class Queue
Queue constructor
#### Queue.prototype.constructor(concurrency)
- `concurrency`: [``][number] asynchronous concurrency
Queue constructor
#### Queue.prototype.wait(msec)
- `msec`: [``][number] wait timeout for single item
_Returns:_ [``][this]
Set wait before processing timeout
#### Queue.prototype.throttle(count\[, interval\])
- `count`: [``][number] item count
- `interval`: [``][number] per interval, optional default: 1000 msec_Returns:_ [``][this]
Throttle to limit throughput
#### Queue.prototype.add(item\[, factor\[, priority\]\])
- `item`: [``][object] to be added
- `factor`: [``][number]|[``][string] type, source, destination
or path, optional
- `priority`: [``][number] optional_Returns:_ [``][this]
Add item to queue
#### Queue.prototype.next(task)
- `task`: [``][array] next task [item, factor, priority]
_Returns:_ [``][this]
Process next item
#### Queue.prototype.takeNext()
_Returns:_ [``][this]
Prepare next item for processing
#### Queue.prototype.pause()
_Returns:_ [``][this]
Pause queue
This function is not completely implemented yet
#### Queue.prototype.resume()
_Returns:_ [``][this]
Resume queue
This function is not completely implemented yet
#### Queue.prototype.clear()
_Returns:_ [``][this]
Clear queue
#### Queue.prototype.timeout(msec, onTimeout)
- `msec`: [``][number] process timeout for single item
- `onTimeout`: [``][function]_Returns:_ [``][this]
Set timeout interval and listener
#### Queue.prototype.process(fn)
- `fn`: [``][function]
- `item`: [``][object]
- `callback`: [``][function]
- `err`: [``][error]|[``][null]
- `result`: ``_Returns:_ [``][this]
Set processing function
#### Queue.prototype.done(fn)
- `fn`: [``][function] done listener
- `err`: [``][error]|[``][null]
- `result`: ``_Returns:_ [``][this]
Set listener on processing done
#### Queue.prototype.success(listener)
- `listener`: [``][function] on success
- `item`: ``_Returns:_ [``][this]
Set listener on processing success
#### Queue.prototype.failure(listener)
- `listener`: [``][function] on failure
- `err`: [``][error]|[``][null]_Returns:_ [``][this]
Set listener on processing error
#### Queue.prototype.drain(listener)
- `listener`: [``][function] on drain
_Returns:_ [``][this]
Set listener on drain Queue
#### Queue.prototype.fifo()
_Returns:_ [``][this]
Switch to FIFO mode (default for Queue)
#### Queue.prototype.lifo()
_Returns:_ [``][this]
Switch to LIFO mode
#### Queue.prototype.priority(flag)
- `flag`: [``][boolean] default: true, false will disable priority mode
_Returns:_ [``][this]
Activate or deactivate priority mode
#### Queue.prototype.roundRobin(flag)
- `flag`: [``][boolean] default: true, false will disable roundRobin
mode_Returns:_ [``][this]
Activate or deactivate round robin mode
#### Queue.prototype.pipe(dest)
- `dest`: [``][queue] destination queue
_Returns:_ [``][this]
Pipe processed items to different queue
### throttle(timeout, fn, ...args)
- `timeout`: [``][number] msec interval
- `fn`: [``][function] to be throttled
- `args`: [``][array] arguments for fn, optional_Returns:_ [``][function]
Get throttling function, executed once per interval
### debounce(timeout, fn, ...args)
- `timeout`: [``][number] msec
- `fn`: [``][function] to be debounced
- `args`: [``][array] arguments for fn, optionalDebounce function, delayed execution
### timeout(timeout, fn, callback)
- `timeout`: [``][number] time interval
- `fn`: [``][function] to be executed
- `callback`: [``][function] callback(...args), on done
- `args`: [``][array]Set timeout for asynchronous function execution
## Contributors
- Timur Shemsedinov (marcusaurelius)
- See github for full [contributors list](https://github.com/metarhia/metasync/graphs/contributors)[asynciterable]: https://tc39.github.io/ecma262/#sec-asynciterable-interface
[asynciterator]: #class-asynciterator
[collector]: #class-collector
[queue]: #class-queue
[object]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
[function]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function
[promise]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
[array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
[error]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
[boolean]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type
[null]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Null_type
[number]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type
[string]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type
[iterable]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols
[this]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this