node-flowless - Less but better control-flow library
flowless is not a flawless :)
Examples
Here is the same example as asyncblock.
var fs = ;var flowless = ; flowless;
Installation
$ npm install flowless
Features
Easily nestable
flowless provides two kind of API for control-flow.
- Runs asynchronous functions immediately:
runSeq()
,runPar()
andrunMap()
.
- Returns a function which runs asynchronous functions:
seq()
,par()
andmap()
.
The former is similar to the function that other control-flow modules (e.g. Async) provide.
On the other hand, the latter returns a function which runs asynchronous functions, rather than running them immediately. Because the returned function is also an asynchronous style, they are easily nestable.
Example:
var flowless = ; flowless;
The structure of this program reflects a control-flow directly.
+-> seven -+
+-> three --> four -+ +-> seven -+
one --> two -+ +--+-> seven -+-> eight --> allDone
+-> five --> six -+ +-> seven -+
...
Easily composable
Example:
{ return flowless;}
{ return flowless;}
You can put them together as follows.
flowless;
Exception handling in the same way as an error
When an error is passed to a callback.
flowless;
When an exception is thrown.
flowless;
In both of the cases, three()
is not called and Error
is passed to
the allDone()
.
Flowless wraps the cause error. It has the information about the location in the control-flow that the error occurred.
Example:
var flowless = require('flowless');flowless.runSeq([ function foo(cb) { cb(null); }, flowless.seq([ function bar(cb) { cb(new Error('Oooops!!')); } ]),], function(err, result) { console.log(err);});
Result:
{ [Error: seq[0] at (/tmp/error.js:6) failed: [Error: Oooops!!]]
cause: [Error: Oooops!!],
history:
[ { operator: 'seq',
index: 0,
location: '(/tmp/error.js:6)',
reason: 'failed' },
{ operator: 'runSeq',
index: 1,
location: '(/tmp/error.js:2)',
reason: 'failed' } ] }
Logging for debug
If NODE\_DEBUG
environment variable contains flowless
,
flowless outputs logs for debug.
For example, the first example of this page, it is output log as follows:
$ NODE_DEBUG=flowless node ex.js
FLOWLESS: BEGIN runSeq at (/tmp/ex.js:4)
FLOWLESS: begin runSeq[0] at (/tmp/ex.js:4) with: [ [Function: next] ]
FLOWLESS: BEGIN par at (/tmp/ex.js:5)
FLOWLESS: begin par[0] at (/tmp/ex.js:5) with: [ [Function], 'path1', 'utf8' ]
FLOWLESS: begin par[1] at (/tmp/ex.js:5) with: [ [Function], 'path2', 'utf8' ]
FLOWLESS: end par[0] at (/tmp/ex.js:5) with: [ null, 'aaa\nbbb\nccc\n' ]
FLOWLESS: end par[1] at (/tmp/ex.js:5) with: [ null, 'xxx\nyyy\nzzz\n' ]
FLOWLESS: END par at (/tmp/ex.js:5) with: [ 'aaa\nbbb\nccc\n', 'xxx\nyyy\nzzz\n' ]
FLOWLESS: end runSeq[0] at (/tmp/ex.js:4) with : [ null, [ 'aaa\nbbb\nccc\n', 'xxx\nyyy\nzzz\n' ] ]
FLOWLESS: begin runSeq[1] at (/tmp/ex.js:4) with: [ [ 'aaa\nbbb\nccc\n', 'xxx\nyyy\nzzz\n' ], [Function: next] ]
FLOWLESS: end runSeq[1] at (/tmp/ex.js:4) with : [ null ]
FLOWLESS: begin runSeq[2] at (/tmp/ex.js:4) with: [ [Function: next] ]
FLOWLESS: end runSeq[2] at (/tmp/ex.js:4) with : [ null, 'aaa\nbbb\nccc\nxxx\nyyy\nzzz\n' ]
FLOWLESS: END runSeq at (/tmp/ex.js:4)
aaa
bbb
ccc
xxx
yyy
zzz
all done
Core API
var flowless = ;
flowless.seq(functions)
Returns an asynchronous style function which runs functions in sequential.
- Arguments
functions
: An array of functions. Each function can be an array as a Function Template that is explained below.
- Returns
- An asynchronous style function which runs
functions
in sequential.
- An asynchronous style function which runs
Returned function is:
function([args...,] cb)
- Arguments
args
: Zero or more arguments that will be passed to first element offunctions
.cb
: A callback function.
If some function in the sequential throws an exception or passes an error
to its callback, no more functions are invoked and cb
is immediately
called with the exception or error.
flowless.runSeq(functions [, cb])
Runs functions in sequential immediately.
- Arguments
functions
: An array of functions. Each function can be an array as a Function Template that is explained below.cb
: A callback function.
Example:
flowless;
is equivalent of:
var fn = flowless;;
flowless.par(functions)
Returns an asynchronous style function which runs functions in parallel.
If any of the functions throw an exception or pass an error to its callback, the main callback is immediately called with the value of the error.
- Arguments
functions
: An array of functions. Each function can be an array as a Function Template that is explained below.
- Returns
- An asynchronous style function which runs
functions
in parallel.
- An asynchronous style function which runs
Returned function is:
function([args...,] cb)
- Arguments
args
: Zero or more arguments that will be passed to all element offunctions
.cb
: A callback function.
If any functions in the parallel throw an exception or pass an error
to its callback, cb
is immediately called with the exception or error.
flowless.runPar(functions [, cb])
Runs functions in parallel immediateley.
- Arguments
functions
: An array of functions. Each function can be an array as a Function Template that is explained below.cb
: A callback function.
Example:
flowless;
is equivalent of:
var fn = flowless;;
flowless.map([concurrency,] fn)
Returns an asynchronous style function which produces a new array of values by mapping each value in the given array through the returned function.
- Arguments
concurrency
: A number of how many functions should be run in parallel. Defaults to10
.fn
: An asynchronous function which takes an element of the array as a first argument. It can be an array as a Function Template that is explained below.
- Returns
- An asynchronous style function which produces a new array of values
by mapping each value in the given
array
throughfn
.
- An asynchronous style function which produces a new array of values
by mapping each value in the given
fn
should be one of:
function(element, cb)
function(element, index, cb)
function(element, index, array, cb)
- Arguments
element
: An element ofarray
passed to returned function.index
: An index number of the element.array
: An array passed to returned function.cb
: A callback function.
Returned function is:
function(array, cb)
- Arguments
array
: An array of values.cb
: A callback function.
If any functions in the parallel throw an exception or pass an error
to its callback, cb
is immediately called with the exception or error.
flowless.runMap([concurrency,] array, fn [, cb])
Produces a new array of values by mapping each value in the given array through the returned function.
- Arguments
concurrency
: A number of how many functions should be run in parallel. Defaults to10
.array
: an array of values.fn
: An asynchronous function. It can be an array as a Function Template that is explained below.cb
: A callback function.
fn
should be one of:
function(element, cb)
function(element, index, cb)
function(element, index, array, cb)
- Arguments
element
: an element ofarray
.index
: An index number of the element.array
:array
passed torunMap()
.cb
: A callback function.
Example:
flowless;
is equivalent of:
var fn = flowless;;
Function Template
A Function template is an array representing a function and its argument.
The first or second element must be a function.
If the first element is not a function,
it will be used as a context (this
) object.
The rest of elements will be used as the arguments of the function.
The array can include a special value,
flowless.first
, flowless.second
and flowless.third
.
When the function is called,
they will be replaced with the actual argument of a corresponding position.
Example:
flowless;
is equivalent of:
flowless;
Extra API
var extras = extras;
extras.array
Provides asynchronous style functions to wrap a method of Array
.
It takes the first argument as this
.
Example:
flowless;
is equivalent of:
flowless;
extras.string
Provides asynchronous style functions to wrap a method of String
.
It takes the first argument as this
.
Example:
flowless;
is equivalent of:
flowless;
extras.generate(args...)
Returns a new asynchronous style function which passes a given arguments to a callback.
- Arguments
args
: Values to be given in a callback.
- Returns
- An asynchronous style function which passes
args
to a callback.
- An asynchronous style function which passes
Example:
flowless;
is equivalent of:
flowless;
extras.bindFirst(target, name)
extras.bindSecond(target, name)
extras.bindThird(target, name)
Returns a new asynchronous style function which binds an argument of the specific position (first, second or third) to a property of a target object.
- Arguments
target
: An object that a value is bound.name
: A string of property name that a value is bound.
- Returns
- An asynchronous style function which binds an argument of the specific
position to a property of
target
object.
- An asynchronous style function which binds an argument of the specific
position to a property of
Example:
var context = {};flowless;
is equivalent of:
var context = {};flowless;
extras.flattenFirst()
extras.flattenSecond()
extras.flattenThird()
Returns a new asynchronous style function which flatten an argument of the specific position (first, second or third).
- Returns
- An asynchronous style function which flatten an argument of the specific position. If an argument is not an array, it is passed to the callback.
Example:
var context = {};flowless;
extras.makeAsync(fn)
Returns a new asynchronous style function which invokes a synchronous function and passes the return value to a callback.
- Arguments
fn
: A synchronous function.
- Returns
- An asynchronous style function which invokes a synchronous function.
Example:
flowless;
is equivalent of:
flowless ...);
Acknowledgment
flowless is inspired by Slide.
License
flowless is licensed under the MIT license.