Understanding Observables in Angular

You could create a whole course about them. Here is a brief overview.

Justyna Kuchta
Jul 20, 2020 · 5 min read
Image for post
Image for post
Photo by Stanislav Kondratiev on Unsplash

Observable is like a data source. In an Angular project, it’s an object we import from a third-party package, rxjs. The observable here is implemented by following an observable pattern where we have an observable and an observer and in between, we have a timeline where we can have multiple events, or data packages, emitted by the observable (depending on the data source of the observable). These events can be triggered programmatically, by user interaction, like a button, HTTP requests, and dozens of other data sources.

The observer and handling the data

No, not the one from Fringe. Who or what is the observer then? It is actually our code, our “observing”, so to say, via a subscribe() function.

We have three ways of handling these packages. We can handle data, errors, or the completion of the observable, because these are the three types of data packages you can receive. It’s in these three that your code gets executed.

What should happen if I receive a data package? What should happen if there is an error or when the observable is completed?

Some observables are never done, like a button that can be clicked a bunch of times, others will resolve with the event (like an HTTP request). Generally, though, they are all used to handle async tasks. All these data sources triggered in your code are async tasks, you don’t know when they will happen or how long they will take and you don’t want to wait until the completion of these events blocking your other code. Historically you would use callbacks or promises, observables are just a different approach that is often the preferred way in Angular. Their major advantage is its operators, which we will talk more about later.

Let’s take a closer look

Observables are constructs to which you subscribe to see changes in data. Params is a good example:

ngOnInit() {
this.route.params.subscribe((params: Params) => {
this.userId = +params.userId
})
}

Our params (of type Params) is a stream of route parameters that gives us a new param when we go to the next page and we subscribe to the userId in these params. It’s a stream of data that gives us new values. Angular uses observables heavily and all we have to do is subscribe to them, but it is good to know how they work, so let’s build our own observable.

It is worth noting that observables are not “baked into” JavaScrip or Typescript but rather managed by a package called “rxjs”.

Params is an observable object and Angular knows it. Any observable object can be subscribed to for changes with the subscribe() method.

Let’s build an observable that emits a new value every second and alerts it to the screen:

onClick() {
interval(1000).subscribe(count => console.log(count))
}

let’s also attach it to a simple button which will trigger our listener when clicked, starting the counter:

<button (click)="onClick()">click me</button>

Now here is the thing. This particular observable will keep emitting values. Even if we switch to another site, it will keep printing an incrementing number to the console ad infinitum. Other observables might not necessarily act this way (like an HTTP request), and it is not always necessary to handle this behavior but in order to avoid memory leaks, it is a good practice to stop the observable when we are finished with it. We do that by storing our observable in a variable of the type Subscription and then by stopping it via the unsubscribe() method. Think of a Subscription as:

Subscription = Observable + subscribe()

Our interval function inside our click handler already creates a subscription, but we are not yet storing it. In order to unsubscribe, we have to store it. For that we need to import Subscription from ‘rxjs’:

import { interval, Subscription } from 'rxjs'

we can now declare a variable where we will later store our subscription

export class SomeComponent implements OnInit {
private clickSub: Subscription
constructor() {} onClick() {
this.clickSub = interval(1000).subscribe(count => console.log(count))
}
}

now that we have stored the subscription, let’s make sure we unsubscribe from it when we no longer need it. It makes sense to do that in ngOnDestroy:

ngOnDestroy() {
this.clickSub.unsubscribe()
}

and here is how the entire component might look like

as you can see we are storing the subscription on line 21. Please note we are storing the subscription, NOT the observable.

this here is the observable:

interval(1000)

It only becomes the subscription when we subscribe to it.

Once we have our subscription stored in clickSub variable, we can then use ngOnDestroy to make sure the subscription is cleared when we leave the component (it would otherwise keep emitting newly updated count and printing it to the console despite us leaving the page potentially causing memory leaks.)

Now, like I previously mentioned we don’t always have to unsubscribe from our observable. The reason why we had to do it here, is because we created the observable. Some Angular objects are observable by nature, and Angular is smart enough to destroy subscriptions attached to them when the component is destroyed. That was the case with our Params object.

Subscribing to errors

Another type of “package” we can subscribe to is an error. Our counter can’t fail, but we could certainly fake an error, this time in an HTTP request.

Let’s rewrite our click handler into an HTTP request fetching data from the New York Times API:

onClick() {    this.clickSub = this.http.get(apiUrl).subscribe(        response => console.log('HTTP response', response),        error => console.log('HTTP Error', error),        () => console.log('HTTP request completed.')    )}

As you can see, it is a great example of how the subscribe() method handles all three types of packages: 1. The data, 2. The error, 3. The resolution.

Here is what it looks like with a successful response

Image for post
Image for post

As you can see we get both the response and the “request completed” notification.

Now, see what happens when we send the request with an incorrect API key (which in this case is part of the URL and I will not share with you here):

Image for post
Image for post

We get notified of the error which also gets handled the way we requested (in this case simply by printing the notification and the error to the console).

Please note that when an observable throws an error, it is no longer necessary to unsubscribe from it as it was “killed” by the error.

I hope this was helpful.

There is one more important thing about the observables and the “rxjs” library, and that’s operators.

When we get data and we listen for it with a subscription, we might want to transform the data we receive. And of course, we could do that after we receive the data, but Angular offers a more elegant way.

Operators deserve its own post, though. Stay tuned!

The Startup

Medium's largest active publication, followed by +756K people. Follow to join our community.

Justyna Kuchta

Written by

Web Developer based in Atlanta, GA. Book worm, cat lover, language geek. Open to new opportunities https://www.linkedin.com/in/justyna-kuchta-ab7b3b16/

The Startup

Medium's largest active publication, followed by +756K people. Follow to join our community.

Justyna Kuchta

Written by

Web Developer based in Atlanta, GA. Book worm, cat lover, language geek. Open to new opportunities https://www.linkedin.com/in/justyna-kuchta-ab7b3b16/

The Startup

Medium's largest active publication, followed by +756K people. Follow to join our community.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store