In the previous blog post, we briefly went over Promises, Observables, and the difference between them through Angular 2’s implementation. Although the promise of going over Observables were made near the end of that post, they were never resolved. Being an oathkeeper that I am, this blog post will be dedicated to the topic of Observables.
For brief recap, below are main differences between Promises and Observables.
|Provides 1 time request of data||Provides multiple request for the duration of subscription.|
|Cannot be canceled. It must wait for a success or failed callback.||Can be canceled using unsubscribe();|
The official documentation of Observables describe it as “A representation of any set of values over any amount of time.” and a lot of the online resources are quick to refer it as “stream”. But as I was learning the topic for the first time, I have not found that to be a good enough of explanation.
Therefore, in interest of approaching the topic with new perspective, this blog post will focus less about what observables are and more about how we utilize the them through a simple code example. Please note that the example focuses on explaining the Observables and does not accurately reflect on our production code. That being said… here we go!
For the code example, I have created an app which consists of 3 components that we call Header, Body and Footer and a service called Login Service. The app has a basic functionality of fake log-in and log-out event.
The user is to fill in the input field in the header component and click the login. At the click event, the app fakes the login procedure.
(Due to WordPress’s limitation, the gif is much smaller than intended. My apologies)
Now, let’s briefly go over the code:
On Line 9, we declare a new instance of BehaviorSubject called this._userData$ with the initial value of null.
But before we proceed further, you may be asking: “What the heck is a Subject? I thought this blog’s topic is on Observables!!”
Subject is just an extension of Observable’s interface; Its traits remain the same as that of Observables (meaning you can still use next(), error(), complete()). However, we are faced with limitations with vanilla Observables because we cannot emit the values we require into the streams. Subject is useful alternative for this example because it provides more control by allowing us to trigger the event manually and push values we need into the the stream.
Another reason for using Subject over Observable is because multiple subscribers to Subject receive same data simultaneously while subscribers to Observables react independently. Similar to how I use my twitter to annoy all 3 of my followers with single tweet, this app uses Subject to send data to 3 components simultaneously. Because we are emitting user information during login procedure, it would be useful for selected components to receive such data all at once.
BehaviorSubject only takes a minor step further from Subject as it allows us to set initial value to the observable. The reason for choosing BehaviorSubject for this example is because we want to set initial value of ‘null’ to reflect our start at the logged out state and push it into the Observable Stream.
In login.service.ts, we use BehaviorSubject submit a null value at time of initialization and actively push values into the Observable stream later; In the login(), we force emit a username value and in the logout(), a null value to the receiving end of the stream: components.
On line 20, the BehaviorSubject is brought in from the login.service.ts and is assigned to the Subscription of this.userData$. As the BehaviorSubject invokes the subscribe function, the Observable Stream is formed for the data to travel from the login.service.ts to the components. Starting from line 21, the Behavior Subject runs a callback function with an argument userData$, which is the very same values that user pushes in.
Now that all the important parts are explained, let’s run over the sequence of the functionalities of the codebase.
At the start of the app, the BehaviorSubject is constructed and pushes in the initial value of ‘null’ into the Observable Stream, which is received by the 3 components that are subscribed to it.
Once the name input is filled and “Login” button is clicked, the input value gets actively pushed through the BehaviorSubject by `this.userData$.next(username)` and is quickly received by the subscribed components.
Similarly, when the “Logout” button is clicked, a value of ‘null’ gets pushed into the stream and distributed to the 3 components. The stream is stay open to support multiple logins and logouts.
At the closing of the app, we use the lifecycle hook of ngOnDestroy to unsubscribe, which marks the end point of the stream to prevent possible memory leak.
That’s all there is to it! As always, thank you for reading and for those just getting exposed to Observables and struggling to grasp its concept, I hope our real world demonstration can provide some insight.
If you require more examples of how we utilize Observables, please also checkout our other blog post. In that example we utilize Subjects to send true/false/null values to the stream to effectively manage multiple modals.
Until next time!
P.S. The entire codebase is made available below incase you’re interested.