Frontend Quick Tips #5 Pipe/Compose - Proper Way to Transform Your Values
No one likes those big articles - that’s why we’re creating Quick Tips - short tips to change your developer's life from the moment you read them.
Those may be some patterns explained in JS code on real-life examples or some techniques for better code.
We must transform our value and pass the result of each function as a parameter of the next one.
This is not scalable and requires some boilerplate code to handle properly.
The pipe pattern which passes the result of a function to the next one (similar as it is used when chaining promises with then/catch).
Much more elegant and readable. How to create such a pipe function? Here is a snippet you can use:
export const pipe = (...fns) => args => fns.reduce((result, nextFun) => nextFun(result), args);
Take your time to understand this small but quite confusing function.
First we take a list of functions and return a function that runs through all of them. By using reduce we are taking the result of a previous function and passing it to the next one.
What about compose?
There is also an alternative to that - a
compose method which has a similar body and result
export const compose = (...fns) => args => fns.reduceRight((result, nextFun) => nextFun(result), args);
The only difference is in direction of data flow. With a pipe your data flows from the first function to another. With compose it starts with the last and flows to the first. Why would you want to reverse the flow? For readability - it’s common in React.
We are reading what wraps our component.
Below are two graphics presenting the difference from:
This pattern is widely used for example in Rxjs (observables), however almost identical pipe implementations can be found in some examples on the web. I do not take credit for this snippet implementation.
Explained more in detail: https://vanslaars.io/blog/create-pipe-function/