Exploring RxJs Operators - filter

In a previous post I gave an introduction to the observable and included some information on piping operators but I feel like each operator deserves its own post even if the post is going to be reasonably small.

In this post, I thought we would look over the filter operator given that it will probably be one of the most commonly used operators for many developers.

As the name suggests filter filters values from the stream of values that an observable emits, let's start with an example:

1| this.keyboardEvents.pipe(
2|     filter(event => event.key === 'Enter'),
3|     tap(() => console.log('Enter pressed!')
4| );



Let's talk about each line of code, line 1 is simple enough; the keyboardEvents observable emits a KeyboardEvent.
Line 2 is where we will focus most of our attention on, the filter operator, in this case, will filter out any KeyboardEvent objects that do not have 'Enter' as its key.
Line 3 just verifies what I have already said around line 2, showing us that the message is only printed to console when we press the enter key on our keyboard.

A really simple example but there are ways we can improve this code, first off let's get some reuse out of our filter logic:

1| private forEnterKey = (keyboardEvent) => (keyboardEvent.key === 'Enter');
2| 
3| private handleEnterPressed = this.keyboardEvents.pipe(

4|     filter(this.forEnterKey),
5|     tap(() => console.log('Enter pressed!'));


Now we have reusable logic for checking to see if an object of KeyboardEvent has a key that equals Enter, we can then reuse this in other pipes or even outside of our pipes altogether. I also believe this is an appropriate encapsulation of logic, when reading our pipe we should not have to read the logic to see what is happening at this level, I find it appropriate to remove as much of the how from pipes as is possible such that at this level we can easily see what transformations and filters are being applied to our stream of events.

Finally and by no means least this separation makes our code much easier to test; testing is a topic I will write about in a future post.

Now let's talk about what we can expect with multiple filters

6| private numbers$ = of(1,2,3,4,5).pipe(
6|     filter(num => num > 3),
6|     tap(num => console.log('Before second filter ' + num)),
6|     filter(num => num < 5),
6|     tap(num => console.log('After second filter ' + num))
6| );

Output:
Before second filter 4
After second filter 4
Before second filter 5


We can see from the output that we get when subscribing to the number$ observable that the filters are executed in exactly the way we expect (as an aside if you do not need operators between filter operators then I would consider one filter after another to be entirely unnecessary).

As we can see filter is a very trivial operator to understand and yet very powerful in how declarative and expressive it allows our code to be.

Comments

Popular posts from this blog

Angular material table with angular 7 - Defining columns using ngFor

Creating contextual drop downs using RxJs, Angular 7 and Angular Material

From nothing to an Angular 7 app running in 5 minutes with AWS