Skip to content

V2: utils: comp()

Eugene Lazutkin edited this page Aug 3, 2022 · 1 revision

(Since 2.2.0)

comp() chains functions provided as arguments and wraps the result in a Transform stream. Functions in a list are efficiently wired together without using streams making the whole construct more performant.

The current version of comp() is based on asFun().

The better alternative to comp() is gen(). Please consider using it if you target Node 10 and up. In general, both gen() and comp() are designed to be drop-in replacements of each other.

Factory function: comp(...fns)

This function takes functions (including asynchronous functions, generators, and asynchronous generators), filters out all falsy values, and if the resulting array is not empty connects them together and wraps them in a Transform stream. Otherwise, it returns null.

Special values described in Chain are recognized:

The final value will be sanitized according to rules defined in Chain.sanitize().

Examples

A trivial example:

const {chain, none} = require('stream-chain');
const comp = require('stream-chain/utils/comp');

const pipeline1 = chain([
  comp(
    x => x * x,
    x => x + 1,
    x => x % 2 ? none : x
  ),
  // ... the rest of the pipeline
]);
// input:  1, 2, 3, 4, 5
// output: 5, 17

// less performant version:
const pipeline2 = chain([
  x => x * x,
  x => x + 1,
  x => x % 2 ? none : x,
  // ... the rest of the pipeline
]);
// input:  1, 2, 3, 4, 5
// output: 5, 17

More contrived example:

const family = chain([
  comp(
    async person => {
      // add supplimental information
      const extra = await getExtraDataFromDB(person.id);
      if (!extra) return none; // skip if not present
      return Object.assign(person, extra);
    },
    person => {
      // construct a full legal name:
      person.legalName = [
        person.firstName,
        person.middleName,
        person.lastName
      ].filter(name => name).join(' ');
      return person;
    },
    async function*(person) {
      yield person;
      // asynchronously retrieve parents
      if (person.father) {
        yield await getPersonFromDB(person.father);
      }
      if (person.mother) {
        yield await getPersonFromDB(person.mother);
      }
      // asynchronously retrieve children, if any
      for (let i = 0; i < person.children; ++i) {
        yield await getPersonFromDB(person.children[i]);
      }
    }
  ),
  new Transform({
    writableObjectMode: true,
    transform(x, _, callback) {
      // transform to text
      callback(null, JSON.stringify(x));
    }
  }),
  zlib.createGzip(),
  fs.createWriteStream('families.json-stream.gz')
]);

people.pipe(family);
Clone this wiki locally