DEV Community

Klish3
Klish3

Posted on

Learning what I thought I knew: Pipe functions

Sooooo, I got owned by a simple test in a NestJs Jest test because I honestly didn't know what I was doing. My favourite development strategy is brute force. I have no problem with this method since I realised it's a process of illumination where I try all that I know before I begin my hunt for answers on stack overflow and the rest of the big scary internet.

To understand how I messed this up, I decided to break down the function I was trying to test into smaller pieces.

But, enough about me.....for now.

The service

The service I was testing looked like this πŸ‘‡πŸΏ

this.service.lookup(reqUrl).pipe(map((res)=>res.map(.)));

Where the lookup function returned an Array wrapped in an RxJs Observable.

The service calls an endpoint to retrieve some data. Basic stuff right. Well from me trying to test this felt like I was stuck inside the upside-down without Jane (aka Eleven).

The first set of errors I got was the .map is not a function, which is the compiler's way of saying:

Array.map(): prototype of Array

'Yoooo, dude, this is not an Array, map won't work here.'

Observable.map(): imported from Rxjs

'Yoooo, dude, this is not an Observable, map won't work here.'

Array vs Observarble pipe

What are the differences between Array map and rxjs map

The error was confusing to me since I thought that the data being returned was an Array. Essentially this wasn't the main problem but I was led down a rabbit hole for 1.5 hours, which led me to write this article.

After my buddy, Toma, fixed it haha, thanks bro ✊🏿

Now time for the pipe dream

Since I can know HOW the service call is invoked and that it returns data, what I didn't understand was what .pipe does.

In a nutshell, .pipe takes what is being returned and passed that returned value to the next function in the chain.


func(args In): funcRes {} <-- our starter function
pipe( <- passes its response into the pipe function
func1(funcRes), <- func1 use it and returns a func1Res
func2(func1Res) <- func2 uses func1Res and returns func2Res
); = func2Res <- out comes our baby func2Res

Another way to break this up is to create a custom pipe function. TypeOfNan made a simple example of how to demonstrate what .pipe does.

// Input string = "Stranger Things Season 4 Episode 7"
// Custom Pipe
const pipe = (...args) => args.reduce((acc, el) => el(acc));

// Create our 3 functions transfer
const titleFunc1 = '10 Weird Facts About Dogs';
const toLowerCaseFunc2 = (str1) => str1.toLowerCase();
const addHyphensFunc3 = (str2) => str2.replace(/\s/g, '-');

const slug = pipe(titleFunc1, toLowerCaseFunc2, addHyphensFunc3);

console.log(slug); 
// Return string = Stranger-things-season-4-episode-7
Enter fullscreen mode Exit fullscreen mode

Now knowing that the pipe function plays 'hot potato' with the return values from the functions passed through it, I can focus on the next, small parts. Thanks for reading I hope this helps.

References

MDN Web docs - Array.prototype.map()

Rxjs - Pipe

Stack overflow - What are the differences between Array map and rxjs map?

TypeOfNan - How to use pipe, the pipeline operator in javascript

Top comments (0)