Savoy.js
Higher-order functions (synchronous and asynchronous each/eachSeries/map/filter/fold) and functions for flow control (parallel/series/waterfall) in under 1 KB.
Why
Savoy’s higher-order functions differ from Async’s in the following ways:
- The signature of the
fn
iterator is different. The cb
callback (invoked to signal the end of each iteration of fn
) is the first argument of fn
. In addition, fn
is also passed the index/key of the current element, and the original collection
itself. - If passed is an Object,
map
and filter
will return an Object. (If passed an Object, Async’s map
and filter
will return an Array.)
Also, mainly this:
Inventing your own wheels gives you a deep appreciation and understanding of how wheels work and what makes a good one.
API
In all of the method signatures below, collection
(in each/eachSeries/map/filter/fold) and fns
(in parallel/series/waterfall) can either be an Array or an Object literal.
each
savoy.each(collection, fn) — synchronous each
savoy.each([1, 2, 3], function(val, i, arr) {
console.log(val, i, arr);
});
-
Break from the loop by explicitly returning false
from fn
:
savoy.each([1, 2, 3], function(val, i, arr) {
console.log(val, i, arr);
if (i === 1) {
return false;
}
});
savoy.each(collection, fn, done) — asynchronous each
savoy.each({ a: 1, b: 2, c: 3 }, function(cb, val, key, obj) {
console.log(val, key, obj);
cb();
}, function(err) {
console.log(err);
});
- The asynchronous function
fn
is called in parallel over each item in collection
. - Invoke the
cb
callback in fn
to signal the end of each iteration of fn
. - The signature of the
cb
callback is cb(err)
. If err
is truthy, the done
callback is called exactly once with the err
. - When
fn
has completed execution over every item in the collection
, the done
callback is called exactly once with a falsy err
.
eachSeries
savoy.eachSeries(collection, fn) — synchronous eachSeries
savoy.eachSeries(collection, fn, done) — asynchronous eachSeries
savoy.each({ a: 1, b: 2, c: 3 }, function(cb, val, key, obj) {
console.log(val, key, obj);
cb();
}, function(err) {
console.log(err);
});
- The asynchronous function
fn
is called in series over each item in collection
. - Invoke the
cb
callback in fn
to signal the end of each iteration of fn
. - The signature of the
cb
callback is cb(err)
. If err
is truthy, we stop iterating over the collection
, and the done
callback is called exactly once with the err
. - When
fn
has completed execution over every item in the collection
, the done
callback is called exactly once with a falsy err
.
map
savoy.map(collection, fn) — synchronous map
var result = savoy.map({ a: 1, b: 2, c: 3 }, function(val, key, obj) {
console.log(val, key, obj);
return val * 2;
});
console.log(result);
savoy.map(collection, fn, done) — asynchronous map
savoy.map([1, 2, 3], function(cb, val, i, arr) {
console.log(val, i, arr);
cb(null, val * 2);
}, function(err, result) {
console.log(err, result);
});
- The asynchronous function
fn
is called in parallel over each item in collection
. - Invoke the
cb
callback in fn
to signal the end of each iteration of fn
. The signature of the cb
callback is cb(err, mapVal)
:
err
— If truthy, the done
callback is called exactly once with the err
.mapVal
— This is accumulated in the result
argument of the done
callback.
- When
fn
has completed execution over every item in the collection
, the done
callback is called exactly once with a falsy err
and the result
of the map. - Note that if
collection
is an Object:
result
will also be an Object.- Items in
result
may not be in the same order as their corresponding items in the original collection
.
filter
savoy.filter(collection, fn) — synchronous filter
var result = savoy.filter([1, 2, 3], function(val, i, arr) {
console.log(val, i, arr);
return val > 1;
});
console.log(result);
savoy.filter(collection, fn, done) — asynchronous filter
savoy.filter({ a: 1, b: 2, c: 3 }, function(cb, val, key, obj) {
console.log(val, key, obj);
cb(null, val > 1);
}, function(err, result) {
console.log(err, result);
});
- The asynchronous function
fn
is called in parallel over each item in collection
. - Invoke the
cb
callback in fn
to signal the end of each iteration of fn
. The signature of the cb
callback is cb(err, predicate)
:
err
— If truthy, the done
callback is called exactly once with the err
.predicate
— If truthy, the current item is added to the result
argument of the done
callback.
- When
fn
has completed execution over every item in the collection
, the done
callback is called exactly once with a falsy err
and the result
of the filter. - Note that if
collection
is an Object:
result
will also be an Object.- Items in
result
may not be in the same relative order as they were in collection
.
fold
savoy.fold(collection, acc, fn) — synchronous fold
var result = savoy.fold({ a: 1, b: 2, c: 3 }, 0, function(acc, val, key, obj) {
console.log(acc, val, key, obj);
return acc + val;
});
console.log(result);
savoy.fold(collection, acc, fn, done) — asynchronous fold
savoy.fold([1, 2, 3], 0, function(cb, acc, val, i, arr) {
console.log(acc, val, i, arr);
cb(null, acc + val);
}, function(err, result) {
console.log(err, result);
});
- The asynchronous function
fn
is called in series over each item in collection
. - Invoke the
cb
callback in fn
to signal the end of each iteration of fn
. The signature of the cb
callback is cb(err, foldVal)
:
err
— If truthy, the done
callback is called exactly once with the err
.foldVal
— This is the value for acc
that is passed to the next iteration of fn
.
- When
fn
has completed execution over every item in the collection
, the done
callback is called exactly once with a falsy err
and the result
of the fold.
parallel
savoy.parallel(fns [, done])
savoy.parallel([
function(cb) {
cb(null, 1);
},
function(cb) {
cb(null, 2);
},
function(cb) {
cb(null, 3);
}
], function(err, result) {
console.log(err, result);
});
- Each function in
fns
is called in parallel. - Invoke the
cb
callback in each function to signal the end of the function. The signature of the cb
callback is cb(err, val)
:
err
— If truthy, the done
callback is called exactly once with the err
.val
— This is accumulated in the result
argument of the done
callback.
- When every function in
fns
has completed execution, the done
callback is called exactly once with a falsy err
and the result
of each function.
series
savoy.series(fns [, done])
savoy.series({
a: function(cb) {
cb(null, 1);
},
b: function(cb) {
cb(null, 2);
},
c: function(cb) {
cb(null, 3);
}
}, function(err, result) {
console.log(err, result);
});
- Each function in
fns
is called in series. - Invoke the
cb
callback in each function to signal the end of the function. The signature of the cb
callback is cb(err, val)
:
err
— If truthy, the done
callback is called exactly once with the err
.val
— This is accumulated in the result
argument of the done
callback.
- When the entire series of functions has completed execution, the
done
callback is called exactly once with a falsy err
and the result
of each function.
waterfall
savoy.waterfall(fns [, done])
savoy.waterfall([
function(cb) {
cb(null, 'a', 'b');
},
function(cb, arg1, arg2) {
console.log(arg1, arg2);
cb(null, 'c');
},
function(cb, arg) {
console.log(arg);
cb(null, 'd', 'e');
}
], function(err, arg1, arg2) {
console.log(err, arg1, arg2);
});
- Each function in
fns
is called in series. - Invoke the
cb
callback in each function to signal the end of the function. The signature of the cb
callback is cb(err [, arg1, arg2, ...])
:
err
— If truthy, the done
callback is called exactly once with the err
.arg1, arg2, ...
— Arguments that are passed on to the next function in fns
.
- When the entire series of functions has completed execution, the
done
callback is called exactly once with a falsy err
and arguments from the last function in fns
.
Installation
Install via npm:
$ npm i --save savoy
Install via bower:
$ bower i --save yuanqing/savoy
To use Savoy in the browser, include the minified script in your HTML:
<body>
<script src="path/to/savoy.min.js"></script>
<script>
</script>
</body>
Changelog
- 0.3.0
- 0.2.0
- Major rewrite to prioritise performance over minimising the file size
- Add
series
- Make synchronous
each
breakable
- 0.1.0
License
MIT license