-
-
Notifications
You must be signed in to change notification settings - Fork 11
V2: utils: gen()
(Since 2.2.0)
gen()
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 gen()
is based on asGen().
gen()
requires Node 10 and up. If you target Node 8, please consider comp(). In general, both gen()
and comp()
are designed to be drop-in replacements of each other.
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().
many()
and none
are superficial in the context of generators and supported mostly for backward compatibility. Generators can naturally return multiple values or no values at all.
A trivial example:
const {chain, none} = require('stream-chain');
const gen = require('stream-chain/utils/gen');
const pipeline1 = chain([
gen(
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([
gen(
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);