Introduction to Observables in Angular

Observables provide a way for you to pass data around your application in a way that is arguably more flexible and declarative than the alternatives. Angular uses the RxJS implementation of Observables to handle many common async operations, including events, routing and handling HTTP requests and responses. In this blog I’ll provide an introduction to Observables in the context of an Angular application.

Why Observables?

Observables are one of many interfaces we can use to handle async operations in JavaScript. In Stephen Fluin’s fantastic talk on Observables and Angular, he says that Observables can be seen as a way of unifying the ideas of Promises, callbacks and data flows and making them easier to work with.

Observables have at least two participants. You have publishers or producers — functions that publish values, and subscribers that consume this data.

Observables provide a new push system for JavaScript.This means that the producer decides when it will provide data to the consumer. Promises in are another type of push system in JavaScript — a resolved promise provides data to callback functions. For example:

When the Promise resolves — a process which might take milliseconds or minutes — the response can be parsed to JSON and console logged. However, while each resolved Promise can only return a single value, an Observable can provide multiple values over time, pushing data to its consumers.

In contrast, a typical function is a pull system, where the function is a producer of data, and the consumer decides where and when the function is called, and pulls one return value from each function call.

For example, the below function will exit after the first return statement.

With Observables, you can call subscriber.next() to return multiple values, as below:

Functions in JavaScript are defined, and are not executed until they are called by a consumer, which then pulls a return value from it. In a similar way, you can create a new Observable but it is not ‘called’ until a consumer subscribes to it, after which point the producer will continue pushing values until the consumer unsubscribes. Functions and Observables are both lazy computations.

The code contained within the scope of the Observable declaration represents the Observable execution. There are three types of values an Observable execution can deliver:

  • “Next”: a value such as a Number, a String, an Object, etc.
  • “Error”: a JavaScript Error or exception.
  • “Complete”: does not send a value.

After an ‘Error’ or ‘Complete’ notification is received, nothing can be delivered afterwards, much like a return statement in a regular function.

Another important thing to note about subscriptions is that by default, each subscription is independent of the other.

Observables help us to normalize the API you use for handling the ‘stream’ of asynchronous browser events that happen when your users interact with the front end of your application — click events, waiting for HTTP responses, interval timers, user form input, and so on.

Handling Observables in Angular

In Angular, rather than directly using subscribe() in your components, you will usually use async pipes. This has a number of advantages.

Instead of waiting for a Promise to resolve, storing the returned value in a variable and using the variable in a template, we can reference our observable directly in the template.

Keeping your subscriptions open while not using them is a memory leak. By using async pipes, you can enroll the async data when the component is loaded, and unload it when it is torn down. Behind the scenes, the framework manages lifecycle so you don’t have to do it yourself. It’s easy to forgot to unsubscribe in ngOnDestroy(), and if you do forget, there won’t be an error, just a silent memory leak.

Summary

Angular uses the RxJS implementation of Observables both under the hood and in its own API. Observables help us to deal with the ‘stream’ of data and user input flowing around a modern frontend application. Async pipes handle the subscription process for us.

London-based developer