Process
There are times where several lines of code are used to process data. Doing a series of transformations to massage into some shape. For example:
This is a perfectly fine bit of code to write, but you’ll notice that the variable being manipulated - input
- is repeated continually. This seems to violate the DRY principle (Don’t Repeat Yourself).
Since we assign it different data types, it’s also difficult at any point to be sure what data type it is. An alternative is to use intermediate variables:
The advantage of this approach is we have more literate code, and we (or our code editor) can be more sure of what each data type is. However it seems wasteful to have to come up with names for all the steps.
We’d really just like to articulate the steps of each processing.
One of the patterns ixfx offers for doing this is Process.flow , which creates a flow of operators (up to 5 are supported). An operator is just a function that takes a value and returns a value.
The flow is encapsulated in a function that accepts an input value and returns an output.
This may not seem too much of an advantage over the original. We still have value
repeated, for example.
However we’re now composing a series of operators as an array, rather than writing lines of code. This allows us to dynamically construct and manipulate flows at run time without needing hard-coded logic.
Another advantage is that operators can be defined, well-tested and re-used instead of ‘reinventing the wheel’.
Operators
A few pre-defined operators are available, see the API docs for full details
Math
- Process.average - returns running average
- Process.max /Process.min - returns largest/smallest seen value
- Process.tally - returns count of values
- Process.sum - returns sum of values
Etc
- Process.rank - returns the ‘best’ value seen so far based on a provided ranking function. This is like min/max but works for objects.
Temporal
- Process.seenLastToUndefined - If the value is same as immediately prior value, undefined is output instead.
- Process.seenToUndefined - If value is the same as any previously seen value undefined is output instead
- Process.seenToUndefinedByKey - as above, but tracks values based on a key rather than storing them up inefficiently.
Logic
- Process.cancelIfUndefined - cancels rest of flow if undefined is an input
- Process.ifNotUndefined - Returns output of a function if input is undefined
- Process.ifUndefined - Returns output of a function if input value is not undefined
Examples
The flow can produce effects, for example:
If you want to process data from an event, define it once, and then use it within the event handler:
Likewise if you wanted to process data from an iterable or generator, use it within a for of
loop or similar. This technique allows us to share the same data processing flow in different parts of the code.
Ternary
Operators can be added conditionally using the ternary operator.