npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

savoy

v0.3.1

Published

Higher-order functions (synchronous and asynchronous each/eachSeries/map/filter/fold) and functions for flow control (parallel/series/waterfall) in under 1 KB.

Downloads

36

Readme

Savoy.js npm Version Build Status Coverage Status

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);
  //=> 1, 0, [ 1, 2, 3 ]
  //=> 2, 1, [ 1, 2, 3 ]
  //=> 3, 2, [ 1, 2, 3 ]
});
  • Break from the loop by explicitly returning false from fn:

    savoy.each([1, 2, 3], function(val, i, arr) {
      console.log(val, i, arr);
      //=> 1, 0, [ 1, 2, 3 ]
      //=> 2, 1, [ 1, 2, 3 ]
      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);
  //=> 1, 'a', { a: 1, b: 2, c: 3 }
  //=> 2, 'b', { a: 1, b: 2, c: 3 }
  //=> 3, 'c', { a: 1, b: 2, c: 3 }
  cb();
}, function(err) {
  console.log(err);
  //=> null
});
  • 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

  • Alias of savoy.each.

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);
  //=> 1, 'a', { a: 1, b: 2, c: 3 }
  //=> 2, 'b', { a: 1, b: 2, c: 3 }
  //=> 3, 'c', { a: 1, b: 2, c: 3 }
  cb();
}, function(err) {
  console.log(err);
  //=> null
});
  • 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);
  //=> 1, 'a', { a: 1, b: 2, c: 3 }
  //=> 2, 'b', { a: 1, b: 2, c: 3 }
  //=> 3, 'c', { a: 1, b: 2, c: 3 }
  return val * 2;
});
console.log(result);
//=> { a: 2, b: 4, c: 6 }

savoy.map(collection, fn, done)asynchronous map

savoy.map([1, 2, 3], function(cb, val, i, arr) {
  console.log(val, i, arr);
  //=> 1, 0, [1, 2, 3]
  //=> 2, 1, [1, 2, 3]
  //=> 3, 2, [1, 2, 3]
  cb(null, val * 2);
}, function(err, result) {
  console.log(err, result);
  //=> null, [2, 4, 6]
});
  • 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):
    1. err — If truthy, the done callback is called exactly once with the err.
    2. 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:
    1. result will also be an Object.
    2. 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);
  //=> 1, 0, [1, 2, 3]
  //=> 2, 1, [1, 2, 3]
  //=> 3, 2, [1, 2, 3]
  return val > 1;
});
console.log(result);
//=> [2, 3]

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);
  //=> 1, 'a', { a: 1, b: 2, c: 3 }
  //=> 2, 'b', { a: 1, b: 2, c: 3 }
  //=> 3, 'c', { a: 1, b: 2, c: 3 }
  cb(null, val > 1);
}, function(err, result) {
  console.log(err, result);
  //=> null, { b: 2, c: 3 }
});
  • 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):
    1. err — If truthy, the done callback is called exactly once with the err.
    2. 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:
    1. result will also be an Object.
    2. 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);
  //=> 1, 'a', { a: 1, b: 2, c: 3 }
  //=> 2, 'b', { a: 1, b: 2, c: 3 }
  //=> 3, 'c', { a: 1, b: 2, c: 3 }
  return acc + val;
});
console.log(result);
//=> 6

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);
  //=> 0, 1, 0, [1, 2, 3]
  //=> 1, 2, 1, [1, 2, 3]
  //=> 3, 3, 2, [1, 2, 3]
  cb(null, acc + val);
}, function(err, result) {
  console.log(err, result);
  //=> null, 6
});
  • 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):
    1. err — If truthy, the done callback is called exactly once with the err.
    2. 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);
  //=> null, [1, 2, 3]
});
  • 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):
    1. err — If truthy, the done callback is called exactly once with the err.
    2. 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);
  //=> null, { a: 1, b: 2, c: 3 }
});
  • 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):
    1. err — If truthy, the done callback is called exactly once with the err.
    2. 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);
    //=> 'a', 'b'
    cb(null, 'c');
  },
  function(cb, arg) {
    console.log(arg);
    //=> 'c'
    cb(null, 'd', 'e');
  }
], function(err, arg1, arg2) {
  console.log(err, arg1, arg2);
  //=> null, 'd', 'e'
});
  • 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, ...]):
    1. err — If truthy, the done callback is called exactly once with the err.
    2. 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>
    // savoy available here
  </script>
</body>

License

MIT