RXJS Real Examples – 1. How to Use Observables to Manage User Data

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
one of the problems with the rxjs documentation is that many of the observables in the docs look something like this to be generic which is fine for the documentation except it doesn't really lend itself to a practical understanding of observables for everyday programming which is what this video is all about [Music] in this video i'm going to be showing you a real-life example of how i've used rxjs in one of my own personal projects just having an understanding of typescript should be enough for background in this video however if you'd like to have a more in-depth introduction to observables and their difference between promises and some of the other vocabulary that is involved in this conversation go ahead and check out my earlier video which is actually why i'm making this video it's a response to all of the wonderful comments from the people who've watched that earlier one i highly recommend it but if you don't have time or if you just want to start learning immediately how to use observables to handle user login i will quickly review all of those terms starting right now so in that video you'll learn that i use an analogy to explain observables working with observables is a bit like programming a line of radio communications an observable is like a little army guy with a radio every time he says something on the radio we're going to say that he emits a message today we're going to be working with a chain of these radio operators which is technically called a pipe and in fact this analogy is especially slick because even though it's only an analogy in rxjs terms each individual unit in that pipe is technically called an operator anyway each of these little dudes these little operators has special orders for how to interpret the message and the type of message that they interpret they act on their orders and then they propagate the message or a variation on it and then finally the result is another observable this message is received by other soldiers who always keep their little radio on or we say that they subscribe to the observable so that's the analogy and the keywords there are observable emits pipe operator subscription and observer which is the people subscribing to the observables observers so here's the objective today i have a database with data about all of my users and i want to retrieve the corresponding user data if and only if that user is logged in i'm going to rely heavily on observables and rxjs to do this because i need to accomplish all of the following first if the user's login status ever changes for example they log in or they log out or they switch users then i need the data to update accordingly secondly if the user's data gets updated like they change their profile picture for example then the data also needs to be updated accordingly thirdly if there's an error accessing the data for example the user is logging in for the first time and their data doesn't exist then i need to initialize their data and then fourth if there's any other error that's encountered i need to retry this whole procedure again so before i code i'm going to label this diagram like a table of contents with all of the correct rxjs terms for these operators so the first part the part that triggers it all is called the source observable and that's a generic term for any observable that you pipe and eventually subscribe to but in this case i'm using a third-party library i'm using firebase authentication and this source observable emits whenever there's a change in the user's authentication the next operator i'm using is called switch map this is the one that will switch from observing the user's authentication status to the user's dock in the database which in this case is cloud firestore but there are two cases here if the user is logged in we can retrieve their document and if the user is not logged in we're going to return null next we have catch error now catch error is only going to be triggered if an error was emitted previously in this pipe catch error is going to identify that an error was thrown what type of error was thrown and it's going to initialize that user's data and return the data that results just in case there are still errors like maybe there's an error creating that data i have retry which is just going to repeat the entire pipe one more time and then last of all i have something called share even though share is the last operator in the sequence it's really important and it could potentially save you a lot of time debugging and getting frustrated because it addresses something about the nature of pipes that i really need to make sure that i convey here see in my earlier analogy when i was talking about the soldiers we kind of think about a message being sent down this line of radio communication and every soldier is going to repeat the message once so for example if soldier f shows up and they want to hear the message that started with soldier a soldier a is going to tell soldier b here is the message and then b is going to tell c here's the message and on and on down the chain it goes but what if another soldier soldier g comes along and wants to hear the message as well naturally we would assume that not much changes the message goes down the chain and both f and g are there to receive it but in pipes every time there's a new subscription to that resulting observable the pipe is going to be executed another time so two observers two executions of that whole pipe so that's why i'm using share share ensures that the entire pipe gets executed once and then that resulting observable is just shared with every subscription to it so for now just take that knowledge that a pipe can be executed multiple times if it's resulting observable is subscribed to multiple times and tuck it away as we go through the example in the actual code i'll revisit that concept and i'll talk about how that influenced the way that i put this example together i'm going to take a look at the code now and like i said this is the genuine article so i'm taking it out of my angular project but you don't need to know angular to follow along we're really only going to be looking at one part up here my imports the part that's relevant are these classes and functions that are coming from rxjs so i've listed basically what i showed you in the table of contents and also these observables then an angular this is called a service services get injected and they run the logic that supports the front end um it's just a class declaration basically it has some fields and it has a constructor and this constructor takes a bunch of other services which we're going to be seeing used in this pipe that i'm about to show you now in the body of this constructor is the code that is the focus of this entire video it's this pipe which you can see from this open parenthesis it ends way down here so it's about 50 lines of code and then in the end there's a subscription and it tells us what we're going to do with that piped observable so let's take a look and see if we can see the structure that i described in my table of contents so we start with the source observable the source observable is coming from this third-party library off which is angular fire off and it's getting an observable which is the user you can actually hover and see that user is the observable of the currently signed in user or it's null so it's null when the user signs out otherwise it gives us a little bit of information about the user when they sign in now you heard me say earlier that the result or the output of a pipe is going to be another observable so we're going to take the result of this pipe and assign it to this handle over here user doc right the objective is to get the user's document from the database so i'm assigning the result of this pipe to user doc and that dollar sign is a convention that indicates that this handle is actually an observable now inside the body of this pipe or i guess this is not a body this is really just arguments that are being passed into this pipe function are a bunch of operators like we said in the table of contents the first operator is switch map and it takes an argument which is a function and the end of the arguments is right here so the next operator is catch error and again actually i can just collapse there so the first operator switch map the second operator is catch error the third operator is retry and then finally we end with share and then the very end we get a resulting observable we assign it to user doc and then what i want to do is i want to assign something to do with this observable and i do that through a subscription so the very next thing you see is we take the user doc we subscribe to it and every emission from that observable carries out these instructions here so the subscription again takes a function as a argument and actually it takes several arguments i've only used one the others are optional but there is a function for what to do when the observable emits if i wanted to i could make another function for what happens if there's an error and then finally i could make a function for what happens when the observable ends or when it is completed or i guess it doesn't really have any arguments for that one okay so for the last one there are no uh parameters for that final function so really the subscription takes three arguments what happens on emission on air and on completion okay and then i've got some more code at the bottom that i've commented out and we'll use in just a few minutes so now let's take a look at each of these operators one by one and understand what they're doing we'll start with switch map let's take a look we have one function as an argument for switch map and the function takes this parameter off user and we're going to check to see if it exists if it does exist and there is a user id then we're going to retrieve the document from cloud firestore now this portion again third party library that i'm using here afs angular firestore i'm going to get the doc using that user's user id and once i have that doc or reference to that doc i'm going to return value changes which again this is just part of that library but value changes returns unobservable so again the switch pipe will switch to observing the document data rather than user off it's still an observable it's just a different observable than the source observable but there is a second case here what if the user is not logged in at all so that's handled in this else statement if the user is not logged in we're just going to return nothing because there is no user data however because i need to return an observable null is not an observable so i use this from rxjs of which just turns whatever its argument is into an observable in either case when we start with the authentication data we switch to one of two observables this one or that one now what happens if something goes wrong this isn't going to go wrong this is straightforward it returns nothing but this could actually create an error for example the data might not exist in the database now exactly how this works is defined and i had to look up the api for angular firestore but basically i have these rules about what kind of data that can be accessed and the kind of error that's going to be returned if you try to retrieve any document at all if you don't have a document you get a permission denied error which is why inside of my catch error again we have one function it's just what do you do when you get an error and if it's a permission denied error we need to initialize a document for this user once a user has a document they stop getting the permission denied error so this piece um not really relevant for what we're looking at today i'm basically using a cloud function right here to generate initialized user data so i create a user i it's just the default user type so it takes an argument there um now i'm using two promise and let's talk very briefly about two promise i could have done this a few different ways let me type another way out for you i could have done this i could have piped and i could have said take one and then from take one off to import that i could have done subscribe okay now what does this do in this one it says i want to take the result from this function and i want to only take one emission and as soon as i take one emission i want to end my subscription so really this is the same thing as a promise a promise doesn't emit multiple times it just gives you one result after it's finished executing so rather than type out pipe take one i've just converted my observable into a promise they basically do the same thing and again if you want more clarification on the differences between promise and observable go ahead and check out my introductory video anyway convert to a promise and then with that single admission we're going to check if it's success or not so if it is a success then i've got a little alert that's going to pop up and say your account's been created that's handled elsewhere in the body of this class and then we're going to return an observable of that data so here it's kind of the same code we saw earlier we get the user doc and this time because it was just created we should get something that works at least that's what we hope now what happens if the user does not successfully initialize their document well then down below on a failure we're going to notify the user that something went wrong and we're going to throw another error which i'll show you how that gets handled in a little bit okay that all happens if the user tries to log in and their account doesn't exist so their permission is denied we initialize their document and then if it's successful we can return an observable just like we did before or we're going to throw an error now this is called catch error so if i throw an error inside of catch air it's going to continue through the pipe until another operator handles that error so this is all inside of the body of this if statement if the permission was denied let's go ahead and collapse that and take a look at the other errors i did write a way to handle what happens if the document already exists so we're just going to propagate the error and if it's any other error we're going to notify the user that it's an error that we did not anticipate and we're going to throw that error so really the only success here is if permission is denied then we create the user and return an observable on their new document otherwise every other case throws an error so what happens next well we get to retry and actually like that this one has some good explanation right here when i hover it says returns an observable that mirrors the source observable with the exception of an error if the source observable calls error this method will re-subscribe to the source observable for a maximum of count re-subscriptions given as a number parameter rather than propagating the error call okay so what does that mean that means that when this catch error fails retry is going to let everything go through unless it's an error and if it is one of those errors it's just going to go right back to the beginning anything else anything that's good then retry is just going to let it go by okay so that brings us to the last one share now share is a complicated one because it has to do with this like strange nature of the pipes every time we subscribe to a resulting observable like this this pipe gets executed each and every time so to see this in action right down below we subscribe to that resulting observable what happens if we type in here a little log message console.log authentication emitted here is the app and it's completion we're going to sign in we log in and as soon as we log in we see authentication emitted okay i'm going to log out and we're going to make a little change here so i'm going to add a second subscription second sub and we'll do over here we'll say console.log first sub so first sub uh second sub and we're going to keep this console log authentication emitted up here save those changes jump back into my app and right now you can see we're actually not logged in right now but it has printed first sub and second sub because we are subscribing to that observable now what we're going to do is sign in and as soon as i do that we see authentication emitted for sub second sub okay it prints out once but that's because i've got the share here what happens if i remove share so we'll comment out share we'll save again now i'm still logged in right now so immediately it's going to emit that change to being logged in but we see that authentication emitted prints twice because i've got my two subscriptions to that pipe and if i added a third one we're going to get three printouts authentication emitted so there really is this redundancy in the execution of this pipe if we're going to subscribe multiple times but the way you go around that is you share and again we see that it's only printing one time so that's the purpose of share down there so that's what i have prepared today this is already a 25 minute video so thank you first of all for watching all the way to the end there were several other questions and things that came up as i was making it that i decided to remove for now this is already a lot of material but if you have any questions go ahead and throw them in the comments i'll answer them when i get a chance and if you'd like to see more videos like this or if you'd like to see videos at a faster pace this one was really a response to some people who asked for more elaborate examples and they had specifically requested that i go slowly if you'd like to just kind of see some more casual examples as i go through code a little bit more quickly go ahead and subscribe i'll definitely follow up on this little series that i seem to be doing on rxjs thank you so much for your participation in all the comments thank you for watching and i hope to see you next time take care
Info
Channel: NeverBenBetter
Views: 5,527
Rating: 4.9422383 out of 5
Keywords: rxjs examples, what is rxjs in angular, what is rxjs and why do we need it, how to write rxjs pipes, what is switchmap, what is catcherror, rxjs share operator, intro to rxjs, what are observables, observables, rxjs, rxjs tutorial, rxjs observables, rxjs observables for dummies, understanding rxjs observables
Id: isI6rpnTIMA
Channel Id: undefined
Length: 23min 2sec (1382 seconds)
Published: Thu Jun 03 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.