This library provides powerful higher-order functions and other utilities for working with asynchronous functions with callbacks or ES6 promises.
Callback utility functions are in
{callbacks} = require \async-ls
and promise based functions are in
{promises} = require \async-ls
There's also a monad library accessible by:
{monads} = require \async-ls
Callback and promise functions are similar in their input arguments and their result. Callback functions return a callback function with the signature of (error, result) -> void
and promise functions return a Promise
object.
To get the individual functions use LiveScript pattern matching syntax:
{
promises: {
LazyPromise, parallel-map, parallel-limited-filter
},
monads: {
filterM, liftM
}
} = require \async-ls
To build:
make build
Build for browsers (using Browserify):
make async-browser.js
Build for browsers (callbacks library only):
make callbacks-browser.js
Build for browsers (promises library only):
make promises-browser.js
To test:
./test.sh
{monads} = require \async-ls
Monads work best in statically typed languages. To make monadic functions
work in LiveScript, we need to pass the type of the monad to many of the monadic operations.
monadize
encapsulates the monad's type: return
aka pure
, fmap
and bind
functions.
monadize ::
(a -> m a) -> # pure
((a -> b) -> m a -> m b) -> # fmap
(m a -> (a -> m b) -> m b) -> # bind
Monad
Left-to-right Kleisli composition of monads.
kcompM :: (Monad m) => (a -> m b) -> (b -> m c) -> (a -> m c)
Remove one level of monadic structure, projecting its bound argument into the outer level.
(Monad m) => m m x -> m x
Filter the list by applying the predicate function to each of its element one-by-one in serial order.
filterM :: (Monad x) => (x -> m Boolean) -> [x] -> m [x]
The foldM
function is analogous to foldl
, except that its result is
encapsulated in a monad.
foldM :: (Monad a) => (a -> b -> m a) -> a -> [b] -> m a
Evaluate each action in the sequence from left to right, and collect the results.
sequenceM :: (Monad x) => [m x] -> m [x]
It is equivalent to sequenceM . (map f)
.
(Monad m) => (x -> m x) -> [x] -> m [x]
Promote a function to a monad.
liftM :: (Monad m) => (a -> r) -> m a -> m r
Promote a function to a monad, scanning the monadic arguments from left to right.
liftM2 :: (Monad m) => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
monad.pureM f `ap` x1 `ap` ... `ap`
is equivalent to (liftMn monad) f x1 x2 ... xn
ap :: (Monad m) => m (a -> b) -> m a -> m b
list-monad :: Monad # []
either-monad :: Monad # [error, right]
writer-monad :: Monad # [value, monoid]
{promises} = require \async-ls
LazyPromise
only starts getting evaluated after then
is called.
LazyPromise : Promise
promise-monad :: Monad
Inject a value into a promise.
returnP :: x -> Promise x
Map a normal function over a promise.
fmapP :: (x -> y) -> Promise x -> Promise y
fmapP
with its arguments flipped.
ffmapP :: Promise x -> (x -> y) -> Promise y
Sequentially compose two promises, passing the value produced by the first as an argument to the second.
bindP :: Promise x -> (x -> Promise y) -> Promise y
bindP
with its arguments flipped.
fbindP :: (x -> Promise y) -> Promise x -> Promise y
Filter the list by applying the promise predicate function to each of its element one-by-one in serial order.
filterP :: (x -> Promise Boolean) -> [x] -> Promise [x]
The foldP
function is analogous to foldl
, except that its result is
encapsulated in a promise.
foldP :: (a -> b -> Promise a) -> a -> [b] -> Promise a
Run its input (an array of Promise
s) in parallel
(without waiting for the previous promise to fulfill),
and return the results encapsulated in a promise.
The returned promise immidiately gets rejected, if any of the promises in the input list fail.
sequenceP :: [Promise x] -> Promise [x]
parallel-map :: (a -> Promise b) -> [a] -> Promise [b]
serial-map :: (a -> Promise b) -> [a] -> Promise [b]
parallel-limited-map :: Int -> (x -> Promise y) -> [x] -> Promise [y]
parallel-filter :: (x -> m Boolean) -> [x] -> m [x]
Synonym for filterP
serial-filter :: (x -> Promise Boolean) -> [x] -> Promise [x]
parallel-limited-filter :: Int -> (x -> Promise Boolean) -> [x] -> Promise x
Run the boolean predicate (that is encapsulated in a promise) on the list in parallel.
The returned promise fulfills as soon as a matching item is found with true
,
otherwise false
if no match was found.
parallel-any :: (x -> Promise Boolean) -> [x] -> Promise Boolean
serial-any :: (x -> m Boolean) -> [x] -> m Boolean
parallel-limited-any :: Int -> (x -> Promise Boolean) -> [x] -> Promise Boolean
parallel-all :: (x -> Promise Boolean) -> [x] -> Promise Boolean
serial-all :: (x -> Promise Boolean) -> [x] -> Promise Boolean
parallel-limited-all :: Int -> (x -> Promise Boolean) -> [x] -> Promise Boolean
Run the boolean predicate (that is encapsulated in a promise) on the list in parallel.
The returned promisefulfills as soon as a matching item is found with the
matching value, otherwise with null
if no match was found.
parallel-find :: (x -> Promise Boolean) -> [x] -> m
serial-find :: (x -> Promise Boolean) -> [x] -> m x
parallel-limited-find :: Int -> (x -> Promise Boolean) -> [x] -> Promise x
Synonym for sequenceP
parallel-sequence :: [Promise x] -> Promise [x]
The serial version of sequenceP
.
To run the list one by one in a serial order, its items
must be instances of LazyPromise
type.
This function runs the list in parallel, if it is a list
of normal Promise
s.
serial-sequence :: [LazyPromise x] -> LazyPromise [x]
parallel-limited-sequence :: Int -> [LazyPromise x] -> LazyPromise [x]
parallel-apply-each :: x -> [x -> Promise y] -> Promise [y]
serial-apply-each :: x -> [x -> Promise y] -> Promise [y]
parallel-limited-apply-each :: x -> [x -> Promise y] -> Promise [y]
Sort the list using the given function for making the comparison between the items.
parallel-sort-by :: (a -> Promise b) -> [a] -> Promise [a]
parallel-sort-with
takes a binary function which compares two items and returns either
a positive number, 0, or a negative number, and sorts the inputted list
using that function.
parallel-sort-with :: (a -> a -> Promise i) -> [a] -> Promise [a]
waterfall :: x -> (x -> Promise x) -> Promise x
Bind a promise monad to an either monad. The result is a promise monad. Since we can think of promise as a superset of either in the way it handles errors.
transform-promise-either :: Promise x -> (x -> Either y) -> Promise y
transform-promise-either
with its arguments flipped.
ftransform-promise-either :: (x -> Either y) -> Promise x -> Promise y
Bind an either monad to a promise monad.
transform-either-promise :: Either x -> (x -> Promise y) -> Promise y
transform-either-promise
with its arguments flipped.
ftransform-either-promise :: (x -> Promise y) -> Either x -> Promise y
Convert the promise object to a callback with the signature of (error, result) -> void
Promise x -> CB x
Make a promise object from a callback with the signature of (result) -> void
, like fs.exist
Cb x -> Promise x
Make a promise object from a callback with the signature of (error, result) -> void
, like fs.stat
CB x -> Promise x
Make a promise object from obj
.
String -> String -> obj -> Promise x
These functions are analogous to their promise-based counterparts that are documented above.
But instead of a Promise
their last argument is a callback. You can think of curried version of these functions as functions that return a function that takes callback
.
{callbacks} = require \prelude-ls
This would be our definition of asynchronous functions:
If function
f
returns functiong
andg
takes acallback
as its only argument; thenf
is an asynchronous function.
Our callbacks will always receive two parameters: (error, result)
.
Here CB a
stands for a callback function with signature: (err, a) -> void
You can get the result of an asynchronous function (with a callback
of type of CB a
) by:
(err, a) <- f
Inject a value into an asynchronous action.
returnA :: x -> CB x
Map a normal function over an asynchronous action.
fmapA :: (x -> y) -> CB x -> CB y
fmapA with its arguments flipped
ffmapA :: CB x -> (x -> y) -> CB y
Sequentially compose two asynchronous actions, passing the value produced by the first as an argument to the second.
bindA :: CB x -> (x -> CB y) -> CB y
bindA with its arguments flipped
fbindA :: (x -> CB y) -> CB x -> CB y
Similar to Left-to-right Kleisli composition, kcompA
composes
two asynchronous actions passing the value produced
by the first as an argument to the second. The result is a new
asynchronous function that takes the argument of the first function.
kcompA :: (x -> CB y) -> (y -> CB z) -> (x -> CB z)
The foldA
function is analogous to foldl
, except that its result is
encapsulated in an asynchronous callback.
foldA :: (a -> b -> m a) -> a -> [b] -> m a
Evaluate each action in the sequence from left to right, and collect the results.
sequenceA :: [CB x] -> CB [x]
Filter the list by applying the asynchronous predicate function.
filterA :: (x -> CB Boolean) -> [x] -> CB [x]
Inject a value into an either action.
returnE :: x -> Either x
fmapE :: (x -> y) -> Either x -> Either y
ffmapE :: Either x -> (x -> y) -> Either y
bindE :: Either x -> (x -> Either y) -> Either y
bindE :: (x -> Either y) -> Either x -> Either y
Left to right Kleisli composition
kcompE :: (x -> Either y) -> (y -> Either z) -> (x -> Either z)
foldE :: (a -> b -> Either a) -> a -> [b] -> Either a
sequenceE :: [Either x] -> Either [x]
transformAE :: CB x -> (x -> Either y) -> CB y
ftransformAE :: (x -> Either y) -> CB x -> CB y
transformEA :: Either x -> (x -> CB y) -> CB y
ftransformEA :: (x -> CB y) -> Either x -> CB y
parallel-map :: (a -> CB b) -> [a] -> CB [b]
Serial Asynchronous Map
serial-map :: (a -> CB b) -> [a] -> CB [b]
Similar to parallel-map
, only no more than
limit
iterators will be simultaneously running at any time.
parallel-map-limited :: Int -> (x -> CB y) -> [x] -> CB [y]
parallel-filter :: (x -> CB Boolean) -> [x] -> CB [x]
serial-filter :: (x -> CB Boolean) -> [x] -> CB [x]
parallel-limited-filter :: Int -> (x -> CB Boolean) -> [x] -> CB x
parallel-any :: (x -> CB Boolean) -> [x] -> CB Boolean
serial-any :: (x -> CB Boolean) -> [x] -> CB Boolean
parallel-limited-any :: Int -> (x -> CB Boolean) -> [x] -> CB Boolean
parallel-all :: (x -> CB Boolean) -> [x] -> CB Boolean
serial-all :: (x -> CB Boolean) -> [x] -> CB Boolean
parallel-limited-all :: Int -> (x -> CB Boolean) -> [x] -> CB Boolean
paralel-find :: (x -> CB Boolean) -> [x] -> CB x
serial-find :: (x -> CB Boolean) -> [x] -> CB x
Sorts a list using the inputted function for making the comparison between the items.
parallel-sort-by :: (a -> CB b) -> [a] -> CB [a]
Takes a binary function which compares two items and returns either a positive number, 0, or a negative number, and sorts the inputted list using that function.
parallel-sort-with :: (a -> a -> CB i) -> [a] -> CB [a]
serial-sequence :: [CB x] -> CB [x]
Run its sole input (a tasks array of functions) in parallel, without waiting until the previous function has completed. If any of the functions pass an error to its callback, the main callback is immediately called with the value of the error. Once the tasks have completed, the results are passed to the final callback as an array.
parallel-sequence :: [CB x] -> CB [x]
parallel-limited-sequence :: Int -> [CB x] -> CB [x]
parallel-apply-each :: x -> [x -> CB y] -> CB [y]
serial-apply-each :: x -> [x -> CB y] -> CB [y]
parallel-limited-apply-each :: x -> [x -> CB y] -> CB [y]
waterfall :: x -> (x -> CB x) -> CB x
serial-fold :: (a -> b -> m a) -> a -> [b] -> m a