- 00:00:02 welcome to this video on
- 00:00:03 rxjs and specifically on observables
- 00:00:07 observers and subscriptions what are all
- 00:00:09 these things how do they work together
- 00:00:11 well like that we have our observable
- 00:00:15 which basically is a wrapper around some
- 00:00:17 data source
- 00:00:18 and data source typically means a stream
- 00:00:21 of values
- 00:00:22 because as you might be aware
- 00:00:23 observables are a concept we typically
- 00:00:26 use for asynchronous data though it's
- 00:00:27 not limited to this that's important too
- 00:00:29 you can also wrap it about any
- 00:00:31 synchronous data source
- 00:00:32 we will see this in this video too so we
- 00:00:35 have that stream of data possibly
- 00:00:37 asynchronous so possible multiple values
- 00:00:39 over time and now we want to do
- 00:00:42 something whenever a new value occurs
- 00:00:44 that is the job of the observer the
- 00:00:46 observer is there
- 00:00:48 to execute some code whenever we receive
- 00:00:51 a new value
- 00:00:52 or also an error or if the observable
- 00:00:54 reports that it is done
- 00:00:57 therefore the observer is the part doing
- 00:00:59 that and we need to connect it to the
- 00:01:01 observable
- 00:01:01 we do it through a subscription
- 00:01:04 subscription basically means
- 00:01:05 with one method to subscribe method we
- 00:01:08 tell an observable
- 00:01:10 our wrapper around that stream of values
- 00:01:13 that someone is caring about these
- 00:01:15 values that someone is listening to them
- 00:01:18 the observer the observer on the other
- 00:01:20 hand
- 00:01:21 implements up to three methods you can
- 00:01:24 implement
- 00:01:24 none of these but then it's not that
- 00:01:26 useful of an observer
- 00:01:28 or just some of these whatever you need
- 00:01:30 the next method
- 00:01:32 will be called by the observable
- 00:01:33 whenever a new
- 00:01:35 value is emitted so whenever we receive
- 00:01:37 a new value
- 00:01:38 the error method it will be called
- 00:01:41 whenever the observable throws an error
- 00:01:43 and the complete method will be called
- 00:01:45 whenever the observable is done
- 00:01:47 so whenever we know that no more values
- 00:01:49 will be emitted in the future
- 00:01:51 side note some observables will of
- 00:01:53 course never finish
- 00:01:55 if you wrap it around a click listener
- 00:01:57 on a button you don't know when this
- 00:01:59 will finish right the user could always
- 00:02:00 click the button
- 00:02:02 but how does the observable know that it
- 00:02:05 should call next error and complete well
- 00:02:08 that is kind of the contract
- 00:02:09 the two observable and observer sign
- 00:02:12 through the subscription
- 00:02:14 the observable knows that it could fire
- 00:02:16 a next an
- 00:02:17 error or a complete method on an
- 00:02:19 observer and the observer on the other
- 00:02:21 hand knows
- 00:02:22 that the observable will only fire one
- 00:02:24 of these three methods
- 00:02:25 so you can easily implement them on the
- 00:02:27 observer
- 00:02:28 and react whenever they are fired so it
- 00:02:31 is this invocation of these methods
- 00:02:33 which allows us to communicate and to
- 00:02:35 handle our data
- 00:02:36 but depicting it like this is not the
- 00:02:39 best way
- 00:02:40 instead what you commonly see is a
- 00:02:42 depiction as
- 00:02:43 a stream as i mentioned an observable in
- 00:02:47 the end just is a wrapper
- 00:02:48 around a stream of values and we can
- 00:02:51 have one value
- 00:02:52 which instantly occurs to have a
- 00:02:54 synchronous data stream
- 00:02:56 or then it's not a stream i guess or we
- 00:02:58 have multiple values
- 00:03:00 whatever the case may be we have our
- 00:03:02 observer with the three methods i
- 00:03:04 mentioned
- 00:03:04 where we can handle any values and we
- 00:03:07 can handle one or multiple values
- 00:03:10 at the end we might have an endpoint
- 00:03:12 when the observable is done
- 00:03:14 and as i mentioned before that might
- 00:03:16 never occur
- 00:03:17 some observables are never done if we do
- 00:03:20 complete the observable though so if we
- 00:03:22 have some data source which eventually
- 00:03:24 finishes
- 00:03:25 then we can call end and we will execute
- 00:03:28 complete
- 00:03:28 if the observer provides it on the
- 00:03:30 observer object
- 00:03:32 we also might have a stream which does
- 00:03:34 not only emit values
- 00:03:36 but which also throws an error at some
- 00:03:38 point of time think about a
- 00:03:40 stream or an observable i should say
- 00:03:42 wrapping an http request
- 00:03:44 we know that we will eventually get back
- 00:03:46 a response
- 00:03:47 but that response could be an error
- 00:03:49 either a time out
- 00:03:50 or maybe a server side error in this
- 00:03:53 case the observable would throw the
- 00:03:54 error
- 00:03:55 and we could handle it in the error
- 00:03:57 function of the observer
- 00:03:59 now seeing that on slides is nice but
- 00:04:02 how do we actually
- 00:04:03 use these concepts where can we see this
- 00:04:05 concept in code
- 00:04:07 well let's take a look i'm on jsfiddle
- 00:04:10 here and i simply chose js fill because
- 00:04:12 i kind of liked the way it looks and how
- 00:04:14 we can work with it
- 00:04:15 and what i'm doing is i'm importing the
- 00:04:18 rx shares package from their cdn which
- 00:04:20 you can find on the official
- 00:04:21 documentation
- 00:04:22 on install it at the very bottom
- 00:04:25 and then i added a button which i can
- 00:04:27 click i
- 00:04:28 listen to any clicks on the button with
- 00:04:30 my observable here so i get an access to
- 00:04:32 the button here
- 00:04:34 and then i simply wrap the button click
- 00:04:36 and i create a new observable with the
- 00:04:38 from event helper method
- 00:04:40 and as a side note if you visit the
- 00:04:42 official documentation at reactivex.io
- 00:04:45 and then you click on observable here
- 00:04:47 you see there are a lot of methods you
- 00:04:49 can use to create a new observable
- 00:04:52 and a lot of these methods are actually
- 00:04:54 nice methods to conveniently create
- 00:04:57 observables which do something specific
- 00:04:59 like here
- 00:05:00 wrapping an event others would emit a
- 00:05:02 new value every x seconds
- 00:05:04 later in this video we'll also see how
- 00:05:06 we can create an observable from scratch
- 00:05:08 but back to this one first i'm wrapping
- 00:05:11 or i can create an observable
- 00:05:13 wrapping this click event and therefore
- 00:05:15 let's open the console
- 00:05:17 whenever i click the button here we see
- 00:05:20 that the value the the x position of my
- 00:05:23 cursor is emitted because that's what
- 00:05:25 i'm getting here
- 00:05:26 so this is how this observable works and
- 00:05:28 what happens here behind the scenes is
- 00:05:31 that this observable has an infinite
- 00:05:34 stream of values
- 00:05:35 a new value is emitted whenever we click
- 00:05:37 that is how that observable is
- 00:05:38 configured
- 00:05:39 and then in the subscribe method we pass
- 00:05:42 an observer
- 00:05:43 now it may not look like this because
- 00:05:44 all a path is a method
- 00:05:46 but the subscribe method takes two
- 00:05:49 possible arguments
- 00:05:50 either a list of functions where the
- 00:05:53 first function is the next function the
- 00:05:55 second argument would be the arrow
- 00:05:57 function and the third argument would be
- 00:05:58 the complete function
- 00:06:00 or a single object which implements
- 00:06:02 these methods
- 00:06:03 so i could also create my observer
- 00:06:06 object here
- 00:06:07 to take the full route so to say
- 00:06:10 create it like that a normal javascript
- 00:06:12 object and there i may have my
- 00:06:14 next method next function
- 00:06:17 we know that for that we will get a
- 00:06:19 value the value which was emitted
- 00:06:21 because next is only called once a new
- 00:06:23 value is emitted
- 00:06:24 and there we could then log value client
- 00:06:28 x in our case or
- 00:06:29 just the value the full event then i can
- 00:06:32 also implement the error of
- 00:06:34 error function now that will never be
- 00:06:37 called on a
- 00:06:38 observable wrapping a click because it
- 00:06:40 can't error
- 00:06:41 basically but we can still add the
- 00:06:43 function
- 00:06:45 and we can also add a complete
- 00:06:48 function however that also will never be
- 00:06:51 called for this example
- 00:06:53 because when we're wrapping this button
- 00:06:55 and we're listening to click events
- 00:06:56 this observable will never complete
- 00:06:58 because we can't tell
- 00:07:00 if the user is going to click this
- 00:07:02 button one more time still
- 00:07:03 i can log completed here however
- 00:07:07 as i said error and complete for this
- 00:07:09 specific observable will never be called
- 00:07:12 now that i created that observer i could
- 00:07:15 also simply
- 00:07:16 pass that observer to my subscribe
- 00:07:18 method and now if i open up the console
- 00:07:20 and clear it here hit ctrl enter to
- 00:07:22 rebuild the code
- 00:07:23 and i click this we get the full mouse
- 00:07:25 event now since i only logged the value
- 00:07:27 and not
- 00:07:28 value client x but you see it works as
- 00:07:31 before
- 00:07:32 simply emitting the value that again
- 00:07:36 is an observable an infinite observable
- 00:07:38 an asynchronous one because we can emit
- 00:07:40 multiple values over time
- 00:07:42 and we use the from event helper method
- 00:07:46 now let's see how we can create an
- 00:07:47 observable from scratch
- 00:07:49 and how we can basically rebuild this
- 00:07:51 exact same behavior
- 00:07:53 with an observable being built from
- 00:07:55 scratch
- 00:07:56 now to build an observable from scratch
- 00:07:58 let's go to the official documentation
- 00:08:00 and see which method might be helpful
- 00:08:02 and there are a lot of methods but the
- 00:08:04 create method here
- 00:08:05 actually is the one i'm looking for with
- 00:08:07 create we can build
- 00:08:09 our own observable right from the start
- 00:08:12 so if we have a look at it
- 00:08:13 you see that create actually takes
- 00:08:16 one argument the observer kind of
- 00:08:20 and you will see how we built that in
- 00:08:22 the next seconds
- 00:08:24 so we already got an observer i will
- 00:08:26 keep that
- 00:08:27 i will comment out this code here
- 00:08:29 however
- 00:08:31 or i can leave the subscribe function
- 00:08:32 even however now i will use
- 00:08:35 rx observable and now create
- 00:08:39 as i mentioned create takes the observer
- 00:08:42 to be precise it takes a function which
- 00:08:44 takes the observer as an argument
- 00:08:46 so we pass a function an anonymous
- 00:08:48 function to create
- 00:08:50 and this function takes an observer
- 00:08:52 object now important
- 00:08:53 we're not passing our observer variable
- 00:08:56 here
- 00:08:56 because keep in mind that's an anonymous
- 00:08:58 function it was like if you were to
- 00:09:00 declare a new one so we simply name the
- 00:09:03 argument this function will eventually
- 00:09:04 get
- 00:09:05 and if we were to name it observer we
- 00:09:07 simply get naming conflicts with our
- 00:09:08 variable
- 00:09:09 we don't pass the data to that function
- 00:09:11 here we define a new one which will
- 00:09:14 eventually
- 00:09:14 receive one argument our xjs will pass
- 00:09:17 that argument for us
- 00:09:19 and this argument will be an observer we
- 00:09:21 know that from the documentation
- 00:09:23 so i will name it ops here now inside of
- 00:09:26 that function
- 00:09:27 we can call ops next to emit
- 00:09:30 a value so let's do that let's emit a
- 00:09:32 value here
- 00:09:33 and if i now hit ctrl enter to build
- 00:09:36 this code and open the
- 00:09:37 console.log you see a value was already
- 00:09:40 emitted
- 00:09:40 because of course we're not listening to
- 00:09:42 any click right now this code
- 00:09:44 immediately gets executed why do we see
- 00:09:47 a
- 00:09:47 value because we subscribe to an
- 00:09:50 observable
- 00:09:51 which takes a function where the
- 00:09:53 function takes the observer
- 00:09:55 which we also pass to subscribe and our
- 00:09:58 x chess now passes
- 00:10:00 our observer which we passed to
- 00:10:02 subscribe
- 00:10:03 to that function and executes that
- 00:10:05 function
- 00:10:06 that is how you create an observable in
- 00:10:08 that function
- 00:10:09 we can call the next method on the
- 00:10:11 observer because remember
- 00:10:13 an observer knows or the observable
- 00:10:16 knows that an observer can have
- 00:10:18 next error or complete so these are the
- 00:10:20 three methods we can call
- 00:10:22 and therefore we see a value if i were
- 00:10:25 to call
- 00:10:25 ops error error here like that
- 00:10:30 clear the console and hit ctrl enter
- 00:10:31 again we see value
- 00:10:33 a value and then error and if i emit
- 00:10:36 another data piece
- 00:10:40 a second value after the error and hit
- 00:10:42 ctrl enter
- 00:10:44 you will see we don't see that because
- 00:10:46 if an error occurs
- 00:10:48 the observable is finished it won't call
- 00:10:51 complete which is why we don't see
- 00:10:53 completed here it doesn't execute that
- 00:10:55 it just executes error but thereafter
- 00:10:58 no more values will be emitted because
- 00:11:00 the observable is done that's just how
- 00:11:02 it behaves after an
- 00:11:03 error now if i call
- 00:11:06 complete instead of error complete
- 00:11:09 without any arguments because we don't
- 00:11:11 pass any to this method you now see a
- 00:11:14 value completed and you
- 00:11:16 also don't see a second value because
- 00:11:18 just like with error the observable is
- 00:11:20 done
- 00:11:21 it's just the case that it didn't fail
- 00:11:23 we didn't get an error but it
- 00:11:25 well completed regularly again any other
- 00:11:28 next calls thereafter won't give us an
- 00:11:31 error but also won't work
- 00:11:33 we don't get that value because the
- 00:11:34 observable was finished before
- 00:11:37 now that's all nice playing around with
- 00:11:39 that but it doesn't really feel like an
- 00:11:41 observable
- 00:11:42 right it's not asynchronous and that
- 00:11:45 from event observable felt much more
- 00:11:48 like it because
- 00:11:48 there we actually wrapped something
- 00:11:51 which was asynchronous
- 00:11:52 and we could see that this stream of
- 00:11:55 data made more
- 00:11:56 sense here we immediately print some
- 00:11:59 values in the end execute some values so
- 00:12:01 where is that an observable remember
- 00:12:04 that i told you that an observable
- 00:12:06 doesn't have to be asynchronous and here
- 00:12:08 it isn't
- 00:12:09 we have a function and this gets
- 00:12:10 executed when we subscribe to it
- 00:12:12 and in that function we just execute
- 00:12:14 some synchronous code
- 00:12:15 therefore our whole observable is not
- 00:12:17 asynchronous
- 00:12:18 we can easily turn it into an
- 00:12:20 asynchronous one though
- 00:12:22 we could simply add a timeout
- 00:12:25 so the normal set timeout method let's
- 00:12:27 set it to two seconds maybe
- 00:12:30 and here we of course have a function so
- 00:12:32 that's the default
- 00:12:33 set timeout code and if i now move ops
- 00:12:37 complete
- 00:12:38 into that you will see that if i now hit
- 00:12:41 ctrl enter
- 00:12:42 we see a different output than before
- 00:12:45 now we get a value and a second value
- 00:12:48 before completed is printed after two
- 00:12:50 seconds
- 00:12:50 and it makes sense because ops complete
- 00:12:53 will not be called before two seconds
- 00:12:55 are over
- 00:12:56 therefore this line is executed first
- 00:12:59 then set timeout is executed but there
- 00:13:01 nothing happens for the first two
- 00:13:02 seconds
- 00:13:03 then it moves on because javascript of
- 00:13:06 course doesn't wait for a set timeout to
- 00:13:08 finish it never does that's nothing
- 00:13:09 observable specific that is how
- 00:13:11 javascript works and therefore it
- 00:13:13 executes this line now
- 00:13:14 and then after two seconds this line is
- 00:13:16 executed now
- 00:13:18 all of a sudden we have an asynchronous
- 00:13:20 observable because now we have a data
- 00:13:22 stream where we have two synchronous
- 00:13:24 values
- 00:13:24 being emitted immediately but then one
- 00:13:27 event happening
- 00:13:28 after two seconds and of course i could
- 00:13:30 also move that into
- 00:13:32 this or in another timeout or something
- 00:13:34 like that i could also create an
- 00:13:36 interval here
- 00:13:37 and if i do that clear this hit ctrl
- 00:13:39 enter we see a value
- 00:13:40 and after two seconds we see a second
- 00:13:42 value and then it's completed
- 00:13:44 and now if i would move that after
- 00:13:46 complete of course
- 00:13:48 a second value would again never be
- 00:13:49 printed because now
- 00:13:51 after two seconds it just is completed
- 00:13:54 and it doesn't wait
- 00:13:55 for for anything else so a second value
- 00:13:57 is not printed
- 00:13:58 i hope this makes more sense it might
- 00:14:01 make even more
- 00:14:02 sense if i now recreate that from event
- 00:14:04 behavior
- 00:14:06 and this is actually pretty easy to do i
- 00:14:09 will comment out all my
- 00:14:11 code i have in there in this
- 00:14:14 observable create function right now
- 00:14:18 and instead i will add new code we have
- 00:14:21 a reference to our button right we do
- 00:14:23 get access to it here
- 00:14:25 and now if i use that button and set on
- 00:14:28 click equal to a function
- 00:14:30 which should eventually get executed i
- 00:14:32 can
- 00:14:33 get my event in there and there i could
- 00:14:35 call ops next event
- 00:14:37 remember i'm still in this function we
- 00:14:38 pass to the create method
- 00:14:40 so we have access to that observer we
- 00:14:42 eventually receive
- 00:14:43 and i'm in the function which i assigned
- 00:14:45 to on click so that will be executed
- 00:14:47 whenever i do click
- 00:14:48 so now if i hit ctrl enter and open my
- 00:14:50 developer tools if i click the button
- 00:14:52 now i'm again logging that mouse event
- 00:14:56 now i basically recreated the same
- 00:14:59 behavior i had before
- 00:15:01 with this from event observable this one
- 00:15:04 here
- 00:15:04 now with my own observable built from
- 00:15:06 scratch but i hope this makes clear
- 00:15:09 how observables work behind the scenes
- 00:15:12 and how you can build them from scratch
- 00:15:15 with the create method
- 00:15:17 now there's one other very important
- 00:15:19 point if we subscribe to that observable
- 00:15:22 like this
- 00:15:23 and keep in mind this specific
- 00:15:25 observable here
- 00:15:26 is an infinite one because we never call
- 00:15:29 complete here in this function we don't
- 00:15:31 call it
- 00:15:32 because of course we always want to
- 00:15:34 listen to more click events
- 00:15:36 if you have an observable which is never
- 00:15:38 completed
- 00:15:40 that poses the danger of a memory leak
- 00:15:43 so you should definitely unsubscribe to
- 00:15:45 any subscriptions which you don't need
- 00:15:47 anymore
- 00:15:48 imagine we have a more complex
- 00:15:50 javascript app here for example a single
- 00:15:52 page application and we navigate to some
- 00:15:54 other place in our app
- 00:15:56 all of a sudden we might not need this
- 00:16:00 anymore we might not need the
- 00:16:01 subscription anymore if we come back we
- 00:16:04 might even create a new one but the old
- 00:16:06 one
- 00:16:06 still lives on in memory that's a memory
- 00:16:09 leak
- 00:16:10 so clean up any subscriptions you don't
- 00:16:13 need anymore
- 00:16:14 and that's super easy to do all you have
- 00:16:16 to do is
- 00:16:17 store that subscription in a variable
- 00:16:19 for example name it subscription or in a
- 00:16:21 property of an object wherever you set
- 00:16:23 it up
- 00:16:24 so here i store the subscription since
- 00:16:26 i'm storing the result of the subscribe
- 00:16:28 method which returns the subscription
- 00:16:30 and therefore i can unsubscribe so i
- 00:16:33 could add a set timeout method here
- 00:16:36 that after five seconds maybe i
- 00:16:39 execute a function now this is outside
- 00:16:42 of any observable that's just in a
- 00:16:43 normal javascript code
- 00:16:45 and there i use my subscription and i
- 00:16:48 call the
- 00:16:48 un subscribe method
- 00:16:52 now watch what happens if i open the
- 00:16:54 console hit ctrl enter
- 00:16:56 you can see i click here and it still
- 00:16:59 prints the values
- 00:17:00 but after a little bit of a time after
- 00:17:03 five seconds to be precise
- 00:17:05 i can click this and no more values are
- 00:17:07 printed
- 00:17:08 because the subscription ended we
- 00:17:10 unsubscribed
- 00:17:11 and that is what you should do if you
- 00:17:12 don't need a subscription anymore
- 00:17:14 and with that i hope i could clear up
- 00:17:16 some of the confusion i hope i could
- 00:17:17 make this
- 00:17:18 concept of observables and subscriptions
- 00:17:21 a bit more
- 00:17:22 clearer i hope you understand
- 00:17:25 how you may build your own observable
- 00:17:27 from scratch
- 00:17:29 and what all these helper methods like
- 00:17:31 from event and so on do behind the
- 00:17:33 scenes
- 00:17:34 see you in other videos hopefully bye