A guide for building custom RxJS (v6) pipeable operators https://angularfirebase.com/lessons/custom-rxjs-operators-by-example/

- Nicholas Jamieson https://medium.com/@cartant
- RxJS Pipeable Ops https://github.com/ReactiveX/rxjs/blob/master/doc/pipeable-operators.md

- PRO Members Firestore JOINS: https://angularfirebase.com/lessons/firestore-joins-similar-to-sql/
2024-02-04T07:19:39.580Z
nova-2
2-general-nova
2024-01-09.29447
30089e05-99d1-4376-b32e-c263170674af
33595274-17b7-4097-8b97-7276f5abc87d
aa721199bbcefd6acce06e0025521066f0220315f78fba696bfaecfae14bff08
67875a7f-c9c4-48a0-aa55-5bdb8a91c34a
deprecated
One of the most valuable things you can learn in RxJS is how to create custom operators.
They will help you reuse common logic throughout your application, But more importantly, you'll understand how Observables work at a more fundamental level.
In this video, we'll cover the basics of custom operators in RxJS, And if you're a pro member, there's a follow-up video about performing joins in Firestore using custom operators.
If you're new to the channel, I can subscribe and you can find the source code at angularfirebase.com.
I like to think of an RxJS operator as middleware for an observable stream.
A chicken goes in, the operator does something, and nuggets come out.
There are tons of operators built into RxJS already, but oftentimes You'll have complex business logic that doesn't fit one of the generic operators.
A common use case that I run into is joining collections and documents together from the Firestore NoSQL database.
The code to do this is relatively complex, but I can wrap it all up in a custom operator and reuse it throughout my application as needed.
I can even do things like state management, air handling, custom logging inside the operator itself.
Now let's go ahead and jump into the code.
For this video, I'll be using the blank TypeScript project on Stackblitz.
I have installed RxJS, and then I'm writing a function called log that will simply write the value that's submitted from the observable on the screen to the right.
So we'll use the of method to create an observable of the string hello, and you can see that it's logged here in the browser.
I'm going to start by creating a more explicit complex operator, and then we'll break this down to make it more simple for your more practical use cases.
An operator itself is just a pure function.
We'll go ahead and create one called toUpperCase and it will just up case the characters in the String.
So this outer function is our operator and then it returns an inner function that returns an observable.
That feels a little confusing at first, but after you do it a couple times, it'll feel pretty natural.
The inner function gives you access to the source observable at that given point in time.
So what you can do is create a new observable by Scribing to the source observable.
Now there's a much cleaner way to do this, but I just wanna show you how it works at a more fundamental level.
We can have this function return a new observable That subscribes to the source observable.
Then we can implement the next callback with this source observable and transform it to whatever value we want to be emitted next.
In our case, we can just call x.
ToUpperCase and that will transform the string to uppercase.
Then inside this method, you can Also, implement the error and complete methods if you wanna control the behavior of those callbacks as well.
And that gives us a completely custom pipeable operator from Scratch.
Now we can put it to use by going down to our observable of hello.
And before subscribing, we'll pipe in the to upper case operator.
And as you can see, that transforms the value to uppercase.
Another thing you might wanna do is pass arguments into your operator.
Let's go ahead and refactor our operator to take the emitted value and raise it to the power of whatever number is passed in as the argument.
We'll go ahead and rename our function to pow.
And in the first function, we can name whatever arguments are able to be passed into it.
Then I'll go down to the operator as it's used in the pipe, pass in the number 3, and then I'll change our observable to 2.
So basically, we're raising 2 to the power of 3.
Then this method is already implemented in plain JavaScript in the math class, we can just go into next and take the emitted value and raise it to the power of n.
And if we run that, you can see it emits a value of 8.
And if we change our argument to 100, you can see it emits a much larger value.
So that's pretty cool, but that's a lot of code for not a whole lot of impact.
We can simplify this code dramatically by piggybacking on existing RXJS operators.
In a lot of cases, you'll be mapping one value to another value.
That's what we're doing right now with this power function.
So let's go ahead and delete this whole part about creating a new observable.
And instead, we'll use the existing map operator from RXJS as our second function.
Map's already going to subscribe to the source observable for us, so all we have to do is return the actual math logic that we want implemented in this operator.
Much cleaner and much easier to read, and it works exactly the same way as the previous operator did.
A fun exercise is to combine rxjs with lodash.
They're both functional libraries, and you can get a lot done with very little code.
I'm going to create a pick numbers operator, And what this will do is filter out any object properties that have number values.
This would take a good amount of code if you were doing it from scratch, But with Lodash, we can use the pick by function, then pass the emitted value as the first argument, and then another Lodash function as the second argument that checks whether or not the property is a number.
Now if we have an observable object, for example, a response from an HTTP call, We can use our custom operator to filter only the object properties that we actually want.
You'll notice in our object that the bar property is a string.
So when we pipe in our operator, it filters that property out from the emitted value.
Now keep in mind that when you're creating custom operators, you're not just limited To map, you can use any existing RxJS operator to create your own custom operator, and you can even use multiple operators together in a pipe.
For example, if I want to create an operator that filters only numbers through the stream, I can use rxjs filter, then pass in the isNumber function from Lodash.
Now if we have an observable that we're only expecting to emit numbers, we can pipe in this operator and filter out anything that is not an actual number.
In this case, 34 are strings, so we should only get 1, 2, and 5 emitted from the observable.
So now that you know the basics of custom RxJS operators, I want to show you a more advanced example.
But first, I wanna give a shout out to Nicholas Jamieson who puts out some amazing content on advanced RxJS concepts and who is also an RxJS core team member.
You should definitely follow him on Medium and Twitter if you're doing anything with RxJS.
Js.
But in this next example, we're going to build an operator that has its own internal state and uses multiple built in RX operators within the custom operator Self.
This can be useful when you have complex business logic within your stream and also need to share data between multiple operators and multiple emitted values.
Normally, you want to keep your functions as pure as possible, meaning given the same inputs, they always produce the same outputs.
So if you declare a variable inside the operator and have other operators read and mutate it, you're violating the principle of Pure Functions.
However, there are some very practical use cases for doing so, and we can do it in a way that's responsible and predictable across all subscribers to an observable.
So if you want to Share information between operators, you should first wrap it in defer.
This is an observable factory function that will ensure any state kept And this operator will happen on a per subscription basis.
So what I'm going to do here is just keep a history of the emitted values that come through the stream.
We can declare the stateful variable inside the defer callback, then all of the operators or functions inside of it will have the ability to read and mutate this variable.
So at this point, we can construct our own custom pipe on the source observable, then the operators can do whatever they want to the state.
In this example, we'll just add a new value to the existing string so we get an ever growing string based on each newly emitted item.
That's just a trivial example.
But in the real world, you might need to share data between multiple operators, and you might need to do more advanced things like caching API calls and things like that.
Or you might need to switch map to multiple related observables, which just becomes really hard to do in a purely functional way.
But in any case, The operator we just built will return a cold observable that has its own internal state.
So each subscriber will get a refresh state based on that subscription.
So I'm actually going to change history to a random number just to demonstrate this a little bit better.
Then we can go and create an interval, and we'll pipe in this custom operator.
If we subscribe to it twice, you'll notice that we get 2 different random numbers.
That's because we're dealing with a cold observable, so they're each creating a new observable on the subscription.
So if you want to make this observable hot and share the state between multiple subscribers, you can just pipe in the share operator when creating the observable, And then that state will be shared between all subscribers.
So now you can see that both subscribers are logging the same random number because they're sharing the same Source and the state still only gets mutated once even though there's multiple subscribers.
In the next video, we'll cover even more advanced concepts with AngularFire 2 and Firestore to join and merge collections and documents together.
I'm gonna go ahead and wrap things up there.
If this video helped you, please like and subscribe.
And if you want to take your development to the next level, consider becoming a pro member at angularfirebase.com.
You'll get access to my full length courses as well was a free book and a whole bunch of other exclusive content.
Thanks for watching and I'll talk to you soon.

Speaker 0: One of the most valuable things you can learn in RxJS is how to create custom operators. They will help you reuse common logic throughout your application, But more importantly, you'll understand how Observables work at a more fundamental level. In this video, we'll cover the basics of custom operators in RxJS, And if you're a pro member, there's a follow-up video about performing joins in Firestore using custom operators. If you're new to the channel, I can subscribe and you can find the source code at angularfirebase.com. I like to think of an RxJS operator as middleware for an observable stream.

A chicken goes in, the operator does something, and nuggets come out. There are tons of operators built into RxJS already, but oftentimes You'll have complex business logic that doesn't fit one of the generic operators. A common use case that I run into is joining collections and documents together from the Firestore NoSQL database. The code to do this is relatively complex, but I can wrap it all up in a custom operator and reuse it throughout my application as needed. I can even do things like state management, air handling, custom logging inside the operator itself.

Now let's go ahead and jump into the code. For this video, I'll be using the blank TypeScript project on Stackblitz. I have installed RxJS, and then I'm writing a function called log that will simply write the value that's submitted from the observable on the screen to the right. So we'll use the of method to create an observable of the string hello, and you can see that it's logged here in the browser. I'm going to start by creating a more explicit complex operator, and then we'll break this down to make it more simple for your more practical use cases.

An operator itself is just a pure function. We'll go ahead and create one called toUpperCase and it will just up case the characters in the String. So this outer function is our operator and then it returns an inner function that returns an observable. That feels a little confusing at first, but after you do it a couple times, it'll feel pretty natural. The inner function gives you access to the source observable at that given point in time.

So what you can do is create a new observable by Scribing to the source observable. Now there's a much cleaner way to do this, but I just wanna show you how it works at a more fundamental level. We can have this function return a new observable That subscribes to the source observable. Then we can implement the next callback with this source observable and transform it to whatever value we want to be emitted next. In our case, we can just call x.

ToUpperCase and that will transform the string to uppercase. Then inside this method, you can Also, implement the error and complete methods if you wanna control the behavior of those callbacks as well. And that gives us a completely custom pipeable operator from Scratch. Now we can put it to use by going down to our observable of hello. And before subscribing, we'll pipe in the to upper case operator.

And as you can see, that transforms the value to uppercase. Another thing you might wanna do is pass arguments into your operator. Let's go ahead and refactor our operator to take the emitted value and raise it to the power of whatever number is passed in as the argument. We'll go ahead and rename our function to pow. And in the first function, we can name whatever arguments are able to be passed into it.

Then I'll go down to the operator as it's used in the pipe, pass in the number 3, and then I'll change our observable to 2. So basically, we're raising 2 to the power of 3. Then this method is already implemented in plain JavaScript in the math class, we can just go into next and take the emitted value and raise it to the power of n. And if we run that, you can see it emits a value of 8. And if we change our argument to 100, you can see it emits a much larger value.

So that's pretty cool, but that's a lot of code for not a whole lot of impact. We can simplify this code dramatically by piggybacking on existing RXJS operators. In a lot of cases, you'll be mapping one value to another value. That's what we're doing right now with this power function. So let's go ahead and delete this whole part about creating a new observable.

And instead, we'll use the existing map operator from RXJS as our second function. Map's already going to subscribe to the source observable for us, so all we have to do is return the actual math logic that we want implemented in this operator. Much cleaner and much easier to read, and it works exactly the same way as the previous operator did. A fun exercise is to combine rxjs with lodash. They're both functional libraries, and you can get a lot done with very little code.

I'm going to create a pick numbers operator, And what this will do is filter out any object properties that have number values. This would take a good amount of code if you were doing it from scratch, But with Lodash, we can use the pick by function, then pass the emitted value as the first argument, and then another Lodash function as the second argument that checks whether or not the property is a number. Now if we have an observable object, for example, a response from an HTTP call, We can use our custom operator to filter only the object properties that we actually want. You'll notice in our object that the bar property is a string. So when we pipe in our operator, it filters that property out from the emitted value.

Now keep in mind that when you're creating custom operators, you're not just limited To map, you can use any existing RxJS operator to create your own custom operator, and you can even use multiple operators together in a pipe. For example, if I want to create an operator that filters only numbers through the stream, I can use rxjs filter, then pass in the isNumber function from Lodash. Now if we have an observable that we're only expecting to emit numbers, we can pipe in this operator and filter out anything that is not an actual number. In this case, 34 are strings, so we should only get 1, 2, and 5 emitted from the observable. So now that you know the basics of custom RxJS operators, I want to show you a more advanced example.

But first, I wanna give a shout out to Nicholas Jamieson who puts out some amazing content on advanced RxJS concepts and who is also an RxJS core team member. You should definitely follow him on Medium and Twitter if you're doing anything with RxJS. Js. But in this next example, we're going to build an operator that has its own internal state and uses multiple built in RX operators within the custom operator Self. This can be useful when you have complex business logic within your stream and also need to share data between multiple operators and multiple emitted values.

Normally, you want to keep your functions as pure as possible, meaning given the same inputs, they always produce the same outputs. So if you declare a variable inside the operator and have other operators read and mutate it, you're violating the principle of Pure Functions. However, there are some very practical use cases for doing so, and we can do it in a way that's responsible and predictable across all subscribers to an observable. So if you want to Share information between operators, you should first wrap it in defer. This is an observable factory function that will ensure any state kept And this operator will happen on a per subscription basis.

So what I'm going to do here is just keep a history of the emitted values that come through the stream. We can declare the stateful variable inside the defer callback, then all of the operators or functions inside of it will have the ability to read and mutate this variable. So at this point, we can construct our own custom pipe on the source observable, then the operators can do whatever they want to the state. In this example, we'll just add a new value to the existing string so we get an ever growing string based on each newly emitted item. That's just a trivial example.

But in the real world, you might need to share data between multiple operators, and you might need to do more advanced things like caching API calls and things like that. Or you might need to switch map to multiple related observables, which just becomes really hard to do in a purely functional way. But in any case, The operator we just built will return a cold observable that has its own internal state. So each subscriber will get a refresh state based on that subscription. So I'm actually going to change history to a random number just to demonstrate this a little bit better.

Then we can go and create an interval, and we'll pipe in this custom operator. If we subscribe to it twice, you'll notice that we get 2 different random numbers. That's because we're dealing with a cold observable, so they're each creating a new observable on the subscription. So if you want to make this observable hot and share the state between multiple subscribers, you can just pipe in the share operator when creating the observable, And then that state will be shared between all subscribers. So now you can see that both subscribers are logging the same random number because they're sharing the same Source and the state still only gets mutated once even though there's multiple subscribers.

In the next video, we'll cover even more advanced concepts with AngularFire 2 and Firestore to join and merge collections and documents together. I'm gonna go ahead and wrap things up there. If this video helped you, please like and subscribe. And if you want to take your development to the next level, consider becoming a pro member at angularfirebase.com. You'll get access to my full length courses as well was a free book and a whole bunch of other exclusive content.

Thanks for watching and I'll talk to you soon.
One of the most valuable things you can learn in RxJS is how to create custom operators. They will help you reuse common logic throughout your application, But more importantly, you'll understand how Observables work at a more fundamental level. In this video, we'll cover the basics of custom operators in RxJS, And if you're a pro member, there's a follow-up video about performing joins in Firestore using custom operators. If you're new to the channel, I can subscribe and you can find the source code at angularfirebase.com. I like to think of an RxJS operator as middleware for an observable stream.
A chicken goes in, the operator does something, and nuggets come out. There are tons of operators built into RxJS already, but oftentimes You'll have complex business logic that doesn't fit one of the generic operators. A common use case that I run into is joining collections and documents together from the Firestore NoSQL database. The code to do this is relatively complex, but I can wrap it all up in a custom operator and reuse it throughout my application as needed. I can even do things like state management, air handling, custom logging inside the operator itself. Now let's go ahead and jump into the code. For this video, I'll be using the blank TypeScript project on Stackblitz. I have installed RxJS, and then I'm writing a function called log that will simply write the value that's submitted from the observable on the screen to the right. So we'll use the of method to create an observable of the string hello, and you can see that it's logged here in the browser. I'm going to start by creating a more explicit complex operator, and then we'll break this down to make it more simple for your more practical use cases. An operator itself is just a pure function. We'll go ahead and create one called toUpperCase and it will just up case the characters in the String.
databases
programming
logic
operations
So this outer function is our operator and then it returns an inner function that returns an observable. That feels a little confusing at first, but after you do it a couple times, it'll feel pretty natural. The inner function gives you access to the source observable at that given point in time. So what you can do is create a new observable by Scribing to the source observable. Now there's a much cleaner way to do this, but I just wanna show you how it works at a more fundamental level. We can have this function return a new observable That subscribes to the source observable. Then we can implement the next callback with this source observable and transform it to whatever value we want to be emitted next. In our case, we can just call x. ToUpperCase and that will transform the string to uppercase. Then inside this method, you can Also, implement the error and complete methods if you wanna control the behavior of those callbacks as well. And that gives us a completely custom pipeable operator from Scratch. Now we can put it to use by going down to our observable of hello.
And before subscribing, we'll pipe in the to upper case operator. And as you can see, that transforms the value to uppercase. Another thing you might wanna do is pass arguments into your operator. Let's go ahead and refactor our operator to take the emitted value and raise it to the power of whatever number is passed in as the argument. We'll go ahead and rename our function to pow. And in the first function, we can name whatever arguments are able to be passed into it. Then I'll go down to the operator as it's used in the pipe, pass in the number 3, and then I'll change our observable to 2. So basically, we're raising 2 to the power of 3. Then this method is already implemented in plain JavaScript in the math class, we can just go into next and take the emitted value and raise it to the power of n. And if we run that, you can see it emits a value of 8. And if we change our argument to 100, you can see it emits a much larger value. So that's pretty cool, but that's a lot of code for not a whole lot of impact. We can simplify this code dramatically by piggybacking on existing RXJS operators. In a lot of cases, you'll be mapping one value to another value. That's what we're doing right now with this power function.
mathematics
operations
logic
programming
So let's go ahead and delete this whole part about creating a new observable. And instead, we'll use the existing map operator from RXJS as our second function. Map's already going to subscribe to the source observable for us, so all we have to do is return the actual math logic that we want implemented in this operator.
Much cleaner and much easier to read, and it works exactly the same way as the previous operator did. A fun exercise is to combine rxjs with lodash. They're both functional libraries, and you can get a lot done with very little code. I'm going to create a pick numbers operator, And what this will do is filter out any object properties that have number values.
programming
This would take a good amount of code if you were doing it from scratch, But with Lodash, we can use the pick by function, then pass the emitted value as the first argument, and then another Lodash function as the second argument that checks whether or not the property is a number. Now if we have an observable object, for example, a response from an HTTP call, We can use our custom operator to filter only the object properties that we actually want. You'll notice in our object that the bar property is a string. So when we pipe in our operator, it filters that property out from the emitted value. Now keep in mind that when you're creating custom operators, you're not just limited To map, you can use any existing RxJS operator to create your own custom operator, and you can even use multiple operators together in a pipe. For example, if I want to create an operator that filters only numbers through the stream, I can use rxjs filter, then pass in the isNumber function from Lodash. Now if we have an observable that we're only expecting to emit numbers, we can pipe in this operator and filter out anything that is not an actual number. In this case, 34 are strings, so we should only get 1, 2, and 5 emitted from the observable. So now that you know the basics of custom RxJS operators, I want to show you a more advanced example. But first, I wanna give a shout out to Nicholas Jamieson who puts out some amazing content on advanced RxJS concepts and who is also an RxJS core team member. You should definitely follow him on Medium and Twitter if you're doing anything with RxJS. Js. But in this next example, we're going to build an operator that has its own internal state and uses multiple built in RX operators within the custom operator Self.
This can be useful when you have complex business logic within your stream and also need to share data between multiple operators and multiple emitted values. Normally, you want to keep your functions as pure as possible, meaning given the same inputs, they always produce the same outputs. So if you declare a variable inside the operator and have other operators read and mutate it, you're violating the principle of Pure Functions. However, there are some very practical use cases for doing so, and we can do it in a way that's responsible and predictable across all subscribers to an observable. So if you want to Share information between operators, you should first wrap it in defer. This is an observable factory function that will ensure any state kept And this operator will happen on a per subscription basis. So what I'm going to do here is just keep a history of the emitted values that come through the stream.
operations
systems
logic
We can declare the stateful variable inside the defer callback, then all of the operators or functions inside of it will have the ability to read and mutate this variable. So at this point, we can construct our own custom pipe on the source observable, then the operators can do whatever they want to the state. In this example, we'll just add a new value to the existing string so we get an ever growing string based on each newly emitted item.
That's just a trivial example. But in the real world, you might need to share data between multiple operators, and you might need to do more advanced things like caching API calls and things like that. Or you might need to switch map to multiple related observables, which just becomes really hard to do in a purely functional way. But in any case, The operator we just built will return a cold observable that has its own internal state. So each subscriber will get a refresh state based on that subscription. So I'm actually going to change history to a random number just to demonstrate this a little bit better. Then we can go and create an interval, and we'll pipe in this custom operator. If we subscribe to it twice, you'll notice that we get 2 different random numbers.
systems
probability
data management
That's because we're dealing with a cold observable, so they're each creating a new observable on the subscription. So if you want to make this observable hot and share the state between multiple subscribers, you can just pipe in the share operator when creating the observable, And then that state will be shared between all subscribers.
networking
So now you can see that both subscribers are logging the same random number because they're sharing the same Source and the state still only gets mutated once even though there's multiple subscribers.
In the next video, we'll cover even more advanced concepts with AngularFire 2 and Firestore to join and merge collections and documents together. I'm gonna go ahead and wrap things up there. If this video helped you, please like and subscribe. And if you want to take your development to the next level, consider becoming a pro member at angularfirebase.com. You'll get access to my full length courses as well was a free book and a whole bunch of other exclusive content. Thanks for watching and I'll talk to you soon.
youtube
books
One of the most valuable things you can learn in RxJS is how to create custom operators. They will help you reuse common logic throughout your application, But more importantly, you'll understand how Observables work at a more fundamental level. In this video, we'll cover the basics of custom operators in RxJS, And if you're a pro member, there's a follow-up video about performing joins in Firestore using custom operators. If you're new to the channel, I can subscribe and you can find the source code at angularfirebase.com. I like to think of an RxJS operator as middleware for an observable stream. A chicken goes in, the operator does something, and nuggets come out. There are tons of operators built into RxJS already, but oftentimes You'll have complex business logic that doesn't fit one of the generic operators. A common use case that I run into is joining collections and documents together from the Firestore NoSQL database. The code to do this is relatively complex, but I can wrap it all up in a custom operator and reuse it throughout my application as needed. I can even do things like state management, air handling, custom logging inside the operator itself. Now let's go ahead and jump into the code. For this video, I'll be using the blank TypeScript project on Stackblitz. I have installed RxJS, and then I'm writing a function called log that will simply write the value that's submitted from the observable on the screen to the right. So we'll use the of method to create an observable of the string hello, and you can see that it's logged here in the browser. I'm going to start by creating a more explicit complex operator, and then we'll break this down to make it more simple for your more practical use cases. An operator itself is just a pure function. We'll go ahead and create one called toUpperCase and it will just up case the characters in the String. So this outer function is our operator and then it returns an inner function that returns an observable. That feels a little confusing at first, but after you do it a couple times, it'll feel pretty natural. The inner function gives you access to the source observable at that given point in time. So what you can do is create a new observable by Scribing to the source observable. Now there's a much cleaner way to do this, but I just wanna show you how it works at a more fundamental level. We can have this function return a new observable That subscribes to the source observable. Then we can implement the next callback with this source observable and transform it to whatever value we want to be emitted next. In our case, we can just call x. ToUpperCase and that will transform the string to uppercase. Then inside this method, you can Also, implement the error and complete methods if you wanna control the behavior of those callbacks as well. And that gives us a completely custom pipeable operator from Scratch. Now we can put it to use by going down to our observable of hello. And before subscribing, we'll pipe in the to upper case operator. And as you can see, that transforms the value to uppercase. Another thing you might wanna do is pass arguments into your operator. Let's go ahead and refactor our operator to take the emitted value and raise it to the power of whatever number is passed in as the argument. We'll go ahead and rename our function to pow. And in the first function, we can name whatever arguments are able to be passed into it. Then I'll go down to the operator as it's used in the pipe, pass in the number 3, and then I'll change our observable to 2. So basically, we're raising 2 to the power of 3. Then this method is already implemented in plain JavaScript in the math class, we can just go into next and take the emitted value and raise it to the power of n. And if we run that, you can see it emits a value of 8. And if we change our argument to 100, you can see it emits a much larger value. So that's pretty cool, but that's a lot of code for not a whole lot of impact. We can simplify this code dramatically by piggybacking on existing RXJS operators. In a lot of cases, you'll be mapping one value to another value. That's what we're doing right now with this power function. So let's go ahead and delete this whole part about creating a new observable. And instead, we'll use the existing map operator from RXJS as our second function. Map's already going to subscribe to the source observable for us, so all we have to do is return the actual math logic that we want implemented in this operator. Much cleaner and much easier to read, and it works exactly the same way as the previous operator did. A fun exercise is to combine rxjs with lodash. They're both functional libraries, and you can get a lot done with very little code. I'm going to create a pick numbers operator, And what this will do is filter out any object properties that have number values. This would take a good amount of code if you were doing it from scratch, But with Lodash, we can use the pick by function, then pass the emitted value as the first argument, and then another Lodash function as the second argument that checks whether or not the property is a number. Now if we have an observable object, for example, a response from an HTTP call, We can use our custom operator to filter only the object properties that we actually want. You'll notice in our object that the bar property is a string. So when we pipe in our operator, it filters that property out from the emitted value. Now keep in mind that when you're creating custom operators, you're not just limited To map, you can use any existing RxJS operator to create your own custom operator, and you can even use multiple operators together in a pipe. For example, if I want to create an operator that filters only numbers through the stream, I can use rxjs filter, then pass in the isNumber function from Lodash. Now if we have an observable that we're only expecting to emit numbers, we can pipe in this operator and filter out anything that is not an actual number. In this case, 34 are strings, so we should only get 1, 2, and 5 emitted from the observable. So now that you know the basics of custom RxJS operators, I want to show you a more advanced example. But first, I wanna give a shout out to Nicholas Jamieson who puts out some amazing content on advanced RxJS concepts and who is also an RxJS core team member. You should definitely follow him on Medium and Twitter if you're doing anything with RxJS. Js. But in this next example, we're going to build an operator that has its own internal state and uses multiple built in RX operators within the custom operator Self. This can be useful when you have complex business logic within your stream and also need to share data between multiple operators and multiple emitted values. Normally, you want to keep your functions as pure as possible, meaning given the same inputs, they always produce the same outputs. So if you declare a variable inside the operator and have other operators read and mutate it, you're violating the principle of Pure Functions. However, there are some very practical use cases for doing so, and we can do it in a way that's responsible and predictable across all subscribers to an observable. So if you want to Share information between operators, you should first wrap it in defer. This is an observable factory function that will ensure any state kept And this operator will happen on a per subscription basis. So what I'm going to do here is just keep a history of the emitted values that come through the stream. We can declare the stateful variable inside the defer callback, then all of the operators or functions inside of it will have the ability to read and mutate this variable. So at this point, we can construct our own custom pipe on the source observable, then the operators can do whatever they want to the state. In this example, we'll just add a new value to the existing string so we get an ever growing string based on each newly emitted item. That's just a trivial example. But in the real world, you might need to share data between multiple operators, and you might need to do more advanced things like caching API calls and things like that. Or you might need to switch map to multiple related observables, which just becomes really hard to do in a purely functional way. But in any case, The operator we just built will return a cold observable that has its own internal state. So each subscriber will get a refresh state based on that subscription. So I'm actually going to change history to a random number just to demonstrate this a little bit better. Then we can go and create an interval, and we'll pipe in this custom operator. If we subscribe to it twice, you'll notice that we get 2 different random numbers. That's because we're dealing with a cold observable, so they're each creating a new observable on the subscription. So if you want to make this observable hot and share the state between multiple subscribers, you can just pipe in the share operator when creating the observable, And then that state will be shared between all subscribers. So now you can see that both subscribers are logging the same random number because they're sharing the same Source and the state still only gets mutated once even though there's multiple subscribers. In the next video, we'll cover even more advanced concepts with AngularFire 2 and Firestore to join and merge collections and documents together. I'm gonna go ahead and wrap things up there. If this video helped you, please like and subscribe. And if you want to take your development to the next level, consider becoming a pro member at angularfirebase.com. You'll get access to my full length courses as well was a free book and a whole bunch of other exclusive content. Thanks for watching and I'll talk to you soon.
One
one
of
of
the
the
most
most
valuable
valuable
things
things
you
you
can
can
learn
learn
in
in
RxJS
rxjs
is
is
how
how
to
to
create
create
custom
custom
operators.
operators
They
they
will
will
help
help
you
you
reuse
reuse
common
common
logic
logic
throughout
throughout
your
your
application,
application
But
but
more
more
importantly,
importantly
you'll
you'll
understand
understand
how
how
Observables
observables
work
work
at
at
a
a
more
more
fundamental
fundamental
level.
level
In
in
this
this
video,
video
we'll
we'll
cover
cover
the
the
basics
basics
of
of
custom
custom
operators
operators
in
in
RxJS,
rxjs
And
and
if
if
you're
you're
a
a
pro
pro
member,
member
there's
there's
a
a
follow-up
follow-up
video
video
about
about
performing
performing
joins
joins
in
in
Firestore
firestore
using
using
custom
custom
operators.
operators
If
if
you're
you're
new
new
to
to
the
the
channel,
channel
I
i
can
can
subscribe
subscribe
and
and
you
you
can
can
find
find
the
the
source
source
code
code
at
at
angularfirebase.com.
angularfirebase.com
I
i
like
like
to
to
think
think
of
of
an
an
RxJS
rxjs
operator
operator
as
as
middleware
middleware
for
for
an
an
observable
observable
stream.
stream
A
a
chicken
chicken
goes
goes
in,
in
the
the
operator
operator
does
does
something,
something
and
and
nuggets
nuggets
come
come
out.
out
There
there
are
are
tons
tons
of
of
operators
operators
built
built
into
into
RxJS
rxjs
already,
already
but
but
oftentimes
oftentimes
You'll
you'll
have
have
complex
complex
business
business
logic
logic
that
that
doesn't
doesn't
fit
fit
one
one
of
of
the
the
generic
generic
operators.
operators
A
a
common
common
use
use
case
case
that
that
I
i
run
run
into
into
is
is
joining
joining
collections
collections
and
and
documents
documents
together
together
from
from
the
the
Firestore
firestore
NoSQL
nosql
database.
database
The
the
code
code
to
to
do
do
this
this
is
is
relatively
relatively
complex,
complex
but
but
I
i
can
can
wrap
wrap
it
it
all
all
up
up
in
in
a
a
custom
custom
operator
operator
and
and
reuse
reuse
it
it
throughout
throughout
my
my
application
application
as
as
needed.
needed
I
i
can
can
even
even
do
do
things
things
like
like
state
state
management,
management
air
air
handling,
handling
custom
custom
logging
logging
inside
inside
the
the
operator
operator
itself.
itself
Now
now
let's
let's
go
go
ahead
ahead
and
and
jump
jump
into
into
the
the
code.
code
For
for
this
this
video,
video
I'll
i'll
be
be
using
using
the
the
blank
blank
TypeScript
typescript
project
project
on
on
Stackblitz.
stackblitz
I
i
have
have
installed
installed
RxJS,
rxjs
and
and
then
then
I'm
i'm
writing
writing
a
a
function
function
called
called
log
log
that
that
will
will
simply
simply
write
write
the
the
value
value
that's
that's
submitted
submitted
from
from
the
the
observable
observable
on
on
the
the
screen
screen
to
to
the
the
right.
right
So
so
we'll
we'll
use
use
the
the
of
of
method
method
to
to
create
create
an
an
observable
observable
of
of
the
the
string
string
hello,
hello
and
and
you
you
can
can
see
see
that
that
it's
it's
logged
logged
here
here
in
in
the
the
browser.
browser
I'm
i'm
going
going
to
to
start
start
by
by
creating
creating
a
a
more
more
explicit
explicit
complex
complex
operator,
operator
and
and
then
then
we'll
we'll
break
break
this
this
down
down
to
to
make
make
it
it
more
more
simple
simple
for
for
your
your
more
more
practical
practical
use
use
cases.
cases
An
an
operator
operator
itself
itself
is
is
just
just
a
a
pure
pure
function.
function
We'll
we'll
go
go
ahead
ahead
and
and
create
create
one
one
called
called
toUpperCase
touppercase
and
and
it
it
will
will
just
just
up
up
case
case
the
the
characters
characters
in
in
the
the
String.
string
So
so
this
this
outer
outer
function
function
is
is
our
our
operator
operator
and
and
then
then
it
it
returns
returns
an
an
inner
inner
function
function
that
that
returns
returns
an
an
observable.
observable
That
that
feels
feels
a
a
little
little
confusing
confusing
at
at
first,
first
but
but
after
after
you
you
do
do
it
it
a
a
couple
couple
times,
times
it'll
it'll
feel
feel
pretty
pretty
natural.
natural
The
the
inner
inner
function
function
gives
gives
you
you
access
access
to
to
the
the
source
source
observable
observable
at
at
that
that
given
given
point
point
in
in
time.
time
So
so
what
what
you
you
can
can
do
do
is
is
create
create
a
a
new
new
observable
observable
by
by
Scribing
scribing
to
to
the
the
source
source
observable.
observable
Now
now
there's
there's
a
a
much
much
cleaner
cleaner
way
way
to
to
do
do
this,
this
but
but
I
i
just
just
wanna
wanna
show
show
you
you
how
how
it
it
works
works
at
at
a
a
more
more
fundamental
fundamental
level.
level
We
we
can
can
have
have
this
this
function
function
return
return
a
a
new
new
observable
observable
That
that
subscribes
subscribes
to
to
the
the
source
source
observable.
observable
Then
then
we
we
can
can
implement
implement
the
the
next
next
callback
callback
with
with
this
this
source
source
observable
observable
and
and
transform
transform
it
it
to
to
whatever
whatever
value
value
we
we
want
want
to
to
be
be
emitted
emitted
next.
next
In
in
our
our
case,
case
we
we
can
can
just
just
call
call
x.
x
ToUpperCase
touppercase
and
and
that
that
will
will
transform
transform
the
the
string
string
to
to
uppercase.
uppercase
Then
then
inside
inside
this
this
method,
method
you
you
can
can
Also,
also
implement
implement
the
the
error
error
and
and
complete
complete
methods
methods
if
if
you
you
wanna
wanna
control
control
the
the
behavior
behavior
of
of
those
those
callbacks
callbacks
as
as
well.
well
And
and
that
that
gives
gives
us
us
a
a
completely
completely
custom
custom
pipeable
pipeable
operator
operator
from
from
Scratch.
scratch
Now
now
we
we
can
can
put
put
it
it
to
to
use
use
by
by
going
going
down
down
to
to
our
our
observable
observable
of
of
hello.
hello
And
and
before
before
subscribing,
subscribing
we'll
we'll
pipe
pipe
in
in
the
the
to
to
upper
upper
case
case
operator.
operator
And
and
as
as
you
you
can
can
see,
see
that
that
transforms
transforms
the
the
value
value
to
to
uppercase.
uppercase
Another
another
thing
thing
you
you
might
might
wanna
wanna
do
do
is
is
pass
pass
arguments
arguments
into
into
your
your
operator.
operator
Let's
let's
go
go
ahead
ahead
and
and
refactor
refactor
our
our
operator
operator
to
to
take
take
the
the
emitted
emitted
value
value
and
and
raise
raise
it
it
to
to
the
the
power
power
of
of
whatever
whatever
number
number
is
is
passed
passed
in
in
as
as
the
the
argument.
argument
We'll
we'll
go
go
ahead
ahead
and
and
rename
rename
our
our
function
function
to
to
pow.
pow
And
and
in
in
the
the
first
first
function,
function
we
we
can
can
name
name
whatever
whatever
arguments
arguments
are
are
able
able
to
to
be
be
passed
passed
into
into
it.
it
Then
then
I'll
i'll
go
go
down
down
to
to
the
the
operator
operator
as
as
it's
it's
used
used
in
in
the
the
pipe,
pipe
pass
pass
in
in
the
the
number
number
3,
3
and
and
then
then
I'll
i'll
change
change
our
our
observable
observable
to
to
2.
2
So
so
basically,
basically
we're
we're
raising
raising
2
2
to
to
the
the
power
power
of
of
3.
3
Then
then
this
this
method
method
is
is
already
already
implemented
implemented
in
in
plain
plain
JavaScript
javascript
in
in
the
the
math
math
class,
class
we
we
can
can
just
just
go
go
into
into
next
next
and
and
take
take
the
the
emitted
emitted
value
value
and
and
raise
raise
it
it
to
to
the
the
power
power
of
of
n.
n
And
and
if
if
we
we
run
run
that,
that
you
you
can
can
see
see
it
it
emits
emits
a
a
value
value
of
of
8.
8
And
and
if
if
we
we
change
change
our
our
argument
argument
to
to
100,
100
you
you
can
can
see
see
it
it
emits
emits
a
a
much
much
larger
larger
value.
value
So
so
that's
that's
pretty
pretty
cool,
cool
but
but
that's
that's
a
a
lot
lot
of
of
code
code
for
for
not
not
a
a
whole
whole
lot
lot
of
of
impact.
impact
We
we
can
can
simplify
simplify
this
this
code
code
dramatically
dramatically
by
by
piggybacking
piggybacking
on
on
existing
existing
RXJS
rxjs
operators.
operators
In
in
a
a
lot
lot
of
of
cases,
cases
you'll
you'll
be
be
mapping
mapping
one
one
value
value
to
to
another
another
value.
value
That's
that's
what
what
we're
we're
doing
doing
right
right
now
now
with
with
this
this
power
power
function.
function
So
so
let's
let's
go
go
ahead
ahead
and
and
delete
delete
this
this
whole
whole
part
part
about
about
creating
creating
a
a
new
new
observable.
observable
And
and
instead,
instead
we'll
we'll
use
use
the
the
existing
existing
map
map
operator
operator
from
from
RXJS
rxjs
as
as
our
our
second
second
function.
function
Map's
map's
already
already
going
going
to
to
subscribe
subscribe
to
to
the
the
source
source
observable
observable
for
for
us,
us
so
so
all
all
we
we
have
have
to
to
do
do
is
is
return
return
the
the
actual
actual
math
math
logic
logic
that
that
we
we
want
want
implemented
implemented
in
in
this
this
operator.
operator
Much
much
cleaner
cleaner
and
and
much
much
easier
easier
to
to
read,
read
and
and
it
it
works
works
exactly
exactly
the
the
same
same
way
way
as
as
the
the
previous
previous
operator
operator
did.
did
A
a
fun
fun
exercise
exercise
is
is
to
to
combine
combine
rxjs
rxjs
with
with
lodash.
lodash
They're
they're
both
both
functional
functional
libraries,
libraries
and
and
you
you
can
can
get
get
a
a
lot
lot
done
done
with
with
very
very
little
little
code.
code
I'm
i'm
going
going
to
to
create
create
a
a
pick
pick
numbers
numbers
operator,
operator
And
and
what
what
this
this
will
will
do
do
is
is
filter
filter
out
out
any
any
object
object
properties
properties
that
that
have
have
number
number
values.
values
This
this
would
would
take
take
a
a
good
good
amount
amount
of
of
code
code
if
if
you
you
were
were
doing
doing
it
it
from
from
scratch,
scratch
But
but
with
with
Lodash,
lodash
we
we
can
can
use
use
the
the
pick
pick
by
by
function,
function
then
then
pass
pass
the
the
emitted
emitted
value
value
as
as
the
the
first
first
argument,
argument
and
and
then
then
another
another
Lodash
lodash
function
function
as
as
the
the
second
second
argument
argument
that
that
checks
checks
whether
whether
or
or
not
not
the
the
property
property
is
is
a
a
number.
number
Now
now
if
if
we
we
have
have
an
an
observable
observable
object,
object
for
for
example,
example
a
a
response
response
from
from
an
an
HTTP
http
call,
call
We
we
can
can
use
use
our
our
custom
custom
operator
operator
to
to
filter
filter
only
only
the
the
object
object
properties
properties
that
that
we
we
actually
actually
want.
want
You'll
you'll
notice
notice
in
in
our
our
object
object
that
that
the
the
bar
bar
property
property
is
is
a
a
string.
string
So
so
when
when
we
we
pipe
pipe
in
in
our
our
operator,
operator
it
it
filters
filters
that
that
property
property
out
out
from
from
the
the
emitted
emitted
value.
value
Now
now
keep
keep
in
in
mind
mind
that
that
when
when
you're
you're
creating
creating
custom
custom
operators,
operators
you're
you're
not
not
just
just
limited
limited
To
to
map,
map
you
you
can
can
use
use
any
any
existing
existing
RxJS
rxjs
operator
operator
to
to
create
create
your
your
own
own
custom
custom
operator,
operator
and
and
you
you
can
can
even
even
use
use
multiple
multiple
operators
operators
together
together
in
in
a
a
pipe.
pipe
For
for
example,
example
if
if
I
i
want
want
to
to
create
create
an
an
operator
operator
that
that
filters
filters
only
only
numbers
numbers
through
through
the
the
stream,
stream
I
i
can
can
use
use
rxjs
rxjs
filter,
filter
then
then
pass
pass
in
in
the
the
isNumber
isnumber
function
function
from
from
Lodash.
lodash
Now
now
if
if
we
we
have
have
an
an
observable
observable
that
that
we're
we're
only
only
expecting
expecting
to
to
emit
emit
numbers,
numbers
we
we
can
can
pipe
pipe
in
in
this
this
operator
operator
and
and
filter
filter
out
out
anything
anything
that
that
is
is
not
not
an
an
actual
actual
number.
number
In
in
this
this
case,
case
34
34
are
are
strings,
strings
so
so
we
we
should
should
only
only
get
get
1,
1
2,
2
and
and
5
5
emitted
emitted
from
from
the
the
observable.
observable
So
so
now
now
that
that
you
you
know
know
the
the
basics
basics
of
of
custom
custom
RxJS
rxjs
operators,
operators
I
i
want
want
to
to
show
show
you
you
a
a
more
more
advanced
advanced
example.
example
But
but
first,
first
I
i
wanna
wanna
give
give
a
a
shout
shout
out
out
to
to
Nicholas
nicholas
Jamieson
jamieson
who
who
puts
puts
out
out
some
some
amazing
amazing
content
content
on
on
advanced
advanced
RxJS
rxjs
concepts
concepts
and
and
who
who
is
is
also
also
an
an
RxJS
rxjs
core
core
team
team
member.
member
You
you
should
should
definitely
definitely
follow
follow
him
him
on
on
Medium
medium
and
and
Twitter
twitter
if
if
you're
you're
doing
doing
anything
anything
with
with
RxJS.
rxjs
Js.
js
But
but
in
in
this
this
next
next
example,
example
we're
we're
going
going
to
to
build
build
an
an
operator
operator
that
that
has
has
its
its
own
own
internal
internal
state
state
and
and
uses
uses
multiple
multiple
built
built
in
in
RX
rx
operators
operators
within
within
the
the
custom
custom
operator
operator
Self.
self
This
this
can
can
be
be
useful
useful
when
when
you
you
have
have
complex
complex
business
business
logic
logic
within
within
your
your
stream
stream
and
and
also
also
need
need
to
to
share
share
data
data
between
between
multiple
multiple
operators
operators
and
and
multiple
multiple
emitted
emitted
values.
values
Normally,
normally
you
you
want
want
to
to
keep
keep
your
your
functions
functions
as
as
pure
pure
as
as
possible,
possible
meaning
meaning
given
given
the
the
same
same
inputs,
inputs
they
they
always
always
produce
produce
the
the
same
same
outputs.
outputs
So
so
if
if
you
you
declare
declare
a
a
variable
variable
inside
inside
the
the
operator
operator
and
and
have
have
other
other
operators
operators
read
read
and
and
mutate
mutate
it,
it
you're
you're
violating
violating
the
the
principle
principle
of
of
Pure
pure
Functions.
functions
However,
however
there
there
are
are
some
some
very
very
practical
practical
use
use
cases
cases
for
for
doing
doing
so,
so
and
and
we
we
can
can
do
do
it
it
in
in
a
a
way
way
that's
that's
responsible
responsible
and
and
predictable
predictable
across
across
all
all
subscribers
subscribers
to
to
an
an
observable.
observable
So
so
if
if
you
you
want
want
to
to
Share
share
information
information
between
between
operators,
operators
you
you
should
should
first
first
wrap
wrap
it
it
in
in
defer.
defer
This
this
is
is
an
an
observable
observable
factory
factory
function
function
that
that
will
will
ensure
ensure
any
any
state
state
kept
kept
And
and
this
this
operator
operator
will
will
happen
happen
on
on
a
a
per
per
subscription
subscription
basis.
basis
So
so
what
what
I'm
i'm
going
going
to
to
do
do
here
here
is
is
just
just
keep
keep
a
a
history
history
of
of
the
the
emitted
emitted
values
values
that
that
come
come
through
through
the
the
stream.
stream
We
we
can
can
declare
declare
the
the
stateful
stateful
variable
variable
inside
inside
the
the
defer
defer
callback,
callback
then
then
all
all
of
of
the
the
operators
operators
or
or
functions
functions
inside
inside
of
of
it
it
will
will
have
have
the
the
ability
ability
to
to
read
read
and
and
mutate
mutate
this
this
variable.
variable
So
so
at
at
this
this
point,
point
we
we
can
can
construct
construct
our
our
own
own
custom
custom
pipe
pipe
on
on
the
the
source
source
observable,
observable
then
then
the
the
operators
operators
can
can
do
do
whatever
whatever
they
they
want
want
to
to
the
the
state.
state
In
in
this
this
example,
example
we'll
we'll
just
just
add
add
a
a
new
new
value
value
to
to
the
the
existing
existing
string
string
so
so
we
we
get
get
an
an
ever
ever
growing
growing
string
string
based
based
on
on
each
each
newly
newly
emitted
emitted
item.
item
That's
that's
just
just
a
a
trivial
trivial
example.
example
But
but
in
in
the
the
real
real
world,
world
you
you
might
might
need
need
to
to
share
share
data
data
between
between
multiple
multiple
operators,
operators
and
and
you
you
might
might
need
need
to
to
do
do
more
more
advanced
advanced
things
things
like
like
caching
caching
API
api
calls
calls
and
and
things
things
like
like
that.
that
Or
or
you
you
might
might
need
need
to
to
switch
switch
map
map
to
to
multiple
multiple
related
related
observables,
observables
which
which
just
just
becomes
becomes
really
really
hard
hard
to
to
do
do
in
in
a
a
purely
purely
functional
functional
way.
way
But
but
in
in
any
any
case,
case
The
the
operator
operator
we
we
just
just
built
built
will
will
return
return
a
a
cold
cold
observable
observable
that
that
has
has
its
its
own
own
internal
internal
state.
state
So
so
each
each
subscriber
subscriber
will
will
get
get
a
a
refresh
refresh
state
state
based
based
on
on
that
that
subscription.
subscription
So
so
I'm
i'm
actually
actually
going
going
to
to
change
change
history
history
to
to
a
a
random
random
number
number
just
just
to
to
demonstrate
demonstrate
this
this
a
a
little
little
bit
bit
better.
better
Then
then
we
we
can
can
go
go
and
and
create
create
an
an
interval,
interval
and
and
we'll
we'll
pipe
pipe
in
in
this
this
custom
custom
operator.
operator
If
if
we
we
subscribe
subscribe
to
to
it
it
twice,
twice
you'll
you'll
notice
notice
that
that
we
we
get
get
2
2
different
different
random
random
numbers.
numbers
That's
that's
because
because
we're
we're
dealing
dealing
with
with
a
a
cold
cold
observable,
observable
so
so
they're
they're
each
each
creating
creating
a
a
new
new
observable
observable
on
on
the
the
subscription.
subscription
So
so
if
if
you
you
want
want
to
to
make
make
this
this
observable
observable
hot
hot
and
and
share
share
the
the
state
state
between
between
multiple
multiple
subscribers,
subscribers
you
you
can
can
just
just
pipe
pipe
in
in
the
the
share
share
operator
operator
when
when
creating
creating
the
the
observable,
observable
And
and
then
then
that
that
state
state
will
will
be
be
shared
shared
between
between
all
all
subscribers.
subscribers
So
so
now
now
you
you
can
can
see
see
that
that
both
both
subscribers
subscribers
are
are
logging
logging
the
the
same
same
random
random
number
number
because
because
they're
they're
sharing
sharing
the
the
same
same
Source
source
and
and
the
the
state
state
still
still
only
only
gets
gets
mutated
mutated
once
once
even
even
though
though
there's
there's
multiple
multiple
subscribers.
subscribers
In
in
the
the
next
next
video,
video
we'll
we'll
cover
cover
even
even
more
more
advanced
advanced
concepts
concepts
with
with
AngularFire
angularfire
2
2
and
and
Firestore
firestore
to
to
join
join
and
and
merge
merge
collections
collections
and
and
documents
documents
together.
together
I'm
i'm
gonna
gonna
go
go
ahead
ahead
and
and
wrap
wrap
things
things
up
up
there.
there
If
if
this
this
video
video
helped
helped
you,
you
please
please
like
like
and
and
subscribe.
subscribe
And
and
if
if
you
you
want
want
to
to
take
take
your
your
development
development
to
to
the
the
next
next
level,
level
consider
consider
becoming
becoming
a
a
pro
pro
member
member
at
at
angularfirebase.com.
angularfirebase.com
You'll
you'll
get
get
access
access
to
to
my
my
full
full
length
length
courses
courses
as
as
well
well
was
was
a
a
free
free
book
book
and
and
a
a
whole
whole
bunch
bunch
of
of
other
other
exclusive
exclusive
content.
content
Thanks
thanks
for
for
watching
watching
and
and
I'll
i'll
talk
talk
to
to
you
you
soon.
soon
success
The speakers discuss the value of custom operators in RxJS and explain how to create efficient workflows. They suggest using a pick numbers operator to combine function libraries and simplify code. They also discuss how to implement a source observable and transform it to whatever value is desired, and how to use a code that filters out object properties and creates new ones. They also introduce a new example of building an operator that has its own internal state and use multiple built in RX operators to create a custom operator. They explain how to use a custom RxJS operator to filter out object properties and create new ones, and how to use the operator to create a new variable and share data between multiple subscribers. They also mention a video on Angularhair 2 and Firiber to join and merge collections and documents.
Custom RxJS Operators by Example
One of the most valuable things you can learn in RxJS is how to create custom operators. They will help you reuse common logic throughout your application, But more importantly, you'll understand how Observables work at a more fundamental level. In this video, we'll cover the basics of custom operators in RxJS, And if you're a pro member, there's a follow-up video about performing joins in Firestore using custom operators. If you're new to the channel, I can subscribe and you can find the source code at angularfirebase.com. I like to think of an RxJS operator as middleware for an observable stream. A chicken goes in, the operator does something, and nuggets come out. There are tons of operators built into RxJS already, but oftentimes You'll have complex business logic that doesn't fit one of the generic operators. A common use case that I run into is joining collections and documents together from the Firestore NoSQL database. The code to do this is relatively complex, but I can wrap it all up in a custom operator and reuse it throughout my application as needed. I can even do things like state management, air handling, custom logging inside the operator itself. Now let's go ahead and jump into the code. For this video, I'll be using the blank TypeScript project on Stackblitz. I have installed RxJS, and then I'm writing a function called log that will simply write the value that's submitted from the observable on the screen to the right. So we'll use the of method to create an observable of the string hello, and you can see that it's logged here in the browser. I'm going to start by creating a more explicit complex operator, and then we'll break this down to make it more simple for your more practical use cases. An operator itself is just a pure function. We'll go ahead and create one called toUpperCase and it will just up case the characters in the String. So this outer function is our operator and then it returns an inner function that returns an observable. That feels a little confusing at first, but after you do it a couple times, it'll feel pretty natural. The inner function gives you access to the source observable at that given point in time. So what you can do is create a new observable by Scribing to the source observable. Now there's a much cleaner way to do this, but I just wanna show you how it works at a more fundamental level. We can have this function return a new observable That subscribes to the source observable. Then we can implement the next callback with this source observable and transform it to whatever value we want to be emitted next. In our case, we can just call x. ToUpperCase and that will transform the string to uppercase. Then inside this method, you can Also, implement the error and complete methods if you wanna control the behavior of those callbacks as well. And that gives us a completely custom pipeable operator from Scratch. Now we can put it to use by going down to our observable of hello. And before subscribing, we'll pipe in the to upper case operator. And as you can see, that transforms the value to uppercase. Another thing you might wanna do is pass arguments into your operator. Let's go ahead and refactor our operator to take the emitted value and raise it to the power of whatever number is passed in as the argument. We'll go ahead and rename our function to pow. And in the first function, we can name whatever arguments are able to be passed into it. Then I'll go down to the operator as it's used in the pipe, pass in the number 3, and then I'll change our observable to 2. So basically, we're raising 2 to the power of 3. Then this method is already implemented in plain JavaScript in the math class, we can just go into next and take the emitted value and raise it to the power of n. And if we run that, you can see it emits a value of 8. And if we change our argument to 100, you can see it emits a much larger value. So that's pretty cool, but that's a lot of code for not a whole lot of impact. We can simplify this code dramatically by piggybacking on existing RXJS operators. In a lot of cases, you'll be mapping one value to another value. That's what we're doing right now with this power function. So let's go ahead and delete this whole part about creating a new observable. And instead, we'll use the existing map operator from RXJS as our second function. Map's already going to subscribe to the source observable for us, so all we have to do is return the actual math logic that we want implemented in this operator. Much cleaner and much easier to read, and it works exactly the same way as the previous operator did. A fun exercise is to combine rxjs with lodash. They're both functional libraries, and you can get a lot done with very little code. I'm going to create a pick numbers operator, And what this will do is filter out any object properties that have number values. This would take a good amount of code if you were doing it from scratch, But with Lodash, we can use the pick by function, then pass the emitted value as the first argument, and then another Lodash function as the second argument that checks whether or not the property is a number. Now if we have an observable object, for example, a response from an HTTP call, We can use our custom operator to filter only the object properties that we actually want. You'll notice in our object that the bar property is a string. So when we pipe in our operator, it filters that property out from the emitted value. Now keep in mind that when you're creating custom operators, you're not just limited To map, you can use any existing RxJS operator to create your own custom operator, and you can even use multiple operators together in a pipe. For example, if I want to create an operator that filters only numbers through the stream, I can use rxjs filter, then pass in the isNumber function from Lodash. Now if we have an observable that we're only expecting to emit numbers, we can pipe in this operator and filter out anything that is not an actual number. In this case, 34 are strings, so we should only get 1, 2, and 5 emitted from the observable. So now that you know the basics of custom RxJS operators, I want to show you a more advanced example. But first, I wanna give a shout out to Nicholas Jamieson who puts out some amazing content on advanced RxJS concepts and who is also an RxJS core team member. You should definitely follow him on Medium and Twitter if you're doing anything with RxJS. Js. But in this next example, we're going to build an operator that has its own internal state and uses multiple built in RX operators within the custom operator Self. This can be useful when you have complex business logic within your stream and also need to share data between multiple operators and multiple emitted values. Normally, you want to keep your functions as pure as possible, meaning given the same inputs, they always produce the same outputs. So if you declare a variable inside the operator and have other operators read and mutate it, you're violating the principle of Pure Functions. However, there are some very practical use cases for doing so, and we can do it in a way that's responsible and predictable across all subscribers to an observable. So if you want to Share information between operators, you should first wrap it in defer. This is an observable factory function that will ensure any state kept And this operator will happen on a per subscription basis. So what I'm going to do here is just keep a history of the emitted values that come through the stream. We can declare the stateful variable inside the defer callback, then all of the operators or functions inside of it will have the ability to read and mutate this variable. So at this point, we can construct our own custom pipe on the source observable, then the operators can do whatever they want to the state. In this example, we'll just add a new value to the existing string so we get an ever growing string based on each newly emitted item. That's just a trivial example. But in the real world, you might need to share data between multiple operators, and you might need to do more advanced things like caching API calls and things like that. Or you might need to switch map to multiple related observables, which just becomes really hard to do in a purely functional way. But in any case, The operator we just built will return a cold observable that has its own internal state. So each subscriber will get a refresh state based on that subscription. So I'm actually going to change history to a random number just to demonstrate this a little bit better. Then we can go and create an interval, and we'll pipe in this custom operator. If we subscribe to it twice, you'll notice that we get 2 different random numbers. That's because we're dealing with a cold observable, so they're each creating a new observable on the subscription. So if you want to make this observable hot and share the state between multiple subscribers, you can just pipe in the share operator when creating the observable, And then that state will be shared between all subscribers. So now you can see that both subscribers are logging the same random number because they're sharing the same Source and the state still only gets mutated once even though there's multiple subscribers. In the next video, we'll cover even more advanced concepts with AngularFire 2 and Firestore to join and merge collections and documents together. I'm gonna go ahead and wrap things up there. If this video helped you, please like and subscribe. And if you want to take your development to the next level, consider becoming a pro member at angularfirebase.com. You'll get access to my full length courses as well was a free book and a whole bunch of other exclusive content. Thanks for watching and I'll talk to you soon.
The speakers discuss the value of custom operators in RxJS and explain how to create efficient workflows. They suggest using a pick numbers operator to combine function libraries and simplify code. They also discuss how to implement a source observable and transform it to whatever value is desired, and how to use a code that filters out object properties and creates new ones. They also introduce a new example of building an operator that has its own internal state and use multiple built in RX operators to create a custom operator. They explain how to use a custom RxJS operator to filter out object properties and create new ones, and how to use the operator to create a new variable and share data between multiple subscribers. They also mention a video on Angularhair 2 and Firiber to join and merge collections and documents.