Post's thumbnail

Jul 4, 2022

RxJS in Angular

RxJS (Reactive Extensions for JavaScript) is a library that enables reactive programming in Angular, which is a programming paradigm focusing on processing data streams. The paradigm shines at dealing with frequently changing data points, as it supports chaining operations together, alleviating the need to declare and assign multiple variables. Incoming data points or events can be filtered, modified and processed as they emerge.

Core Concept

In a conventional, imperative programming paradigm, expressions get called explicitly. Typically, a set of parameters are provided as inputs for an expression, let's assume var a = 1 and var b = 1 . To calculate the sum of a and b, the following function could be declared:

sum(a: number, b: number) => { return a + b }

After calling the function, the expected result 2 can be assigend to a thrid variable as follows: var c = sum(a, b). However, the value of b may have changed to 2 during the execution of the sum function. Traditionally, we had to explicitly reevaluate the function to get the new sum of 1 + 2. However, in reactive programming, expressions will be reevaluated automatically, if an input parameter changes. In our example, the value of c would be automatically be updated to 3 as soon as b get changed from 1 to 2.

Building Blocks

There are three major building blocks, making RxJS a valuable extention to a wide variety of Angular applications:

  1. Observables: A stream of future values or events that can be observed.
  2. Subscriptions: Oberservables alone do not store any values. They serve merely as conduits for data. By calling the subscribe method on an observable, the values following through an observable are getting fetched.
  3. Pipe Operators: Set of operations including map, filter, concat, flatMap, used to transform data.

Example

Let's take a closer look at how RxJS can be used in an Angular controller. Assuming we like to display a list of blog posts, we could introduce a PostService that performs a backend request and returns an object of type Observable<Post[]>. This is fairly standard as Angular's build in HttpClient used to perform backend calls returns Observables by default.

In this example, we have declared a posts variables that is also of type Observable<Post[]>, allowing us to assign the return value of the fetchPosts method to the variable inside the ngOnInit lifecycle hook. As stated above, we need to subscribe to the posts observable in order to actually retrieve the desired block posts.

Calling the Observable's subscribe method would be possible here, but Angular provides a build-in async pipe for subscribing to a Observables directly in the HTML template. Using the async pipe rather than the subscribe method has the benefit that Angular handles the disposal of the subscription. Normally, we had to manually unsubscribe from an Observable, thus I would almost always recommend to utilize Angular's async pipe. After having applied the async pipe, we can iterate over the blog posts via *ngFor like over any standard variable. However, if the result of the fetchPosts method changes, the displayed list in the HTML template gets updated automatically without the need to execute the function again.

PostController

public posts: Observable<Post[]>;

constructor(private readonly postService: PostService) {}

ngOnInit(): void {
    this.posts = this.fetchPosts();
}

private fetchPosts(searchTerm?: string): Observable<Post[]> {
    return this.postService.getPosts();
}

Corresponding template

<div *ngFor="let post of posts | async">{{ post.title }}</div>

This article covered only a simple introduction to a fairly large and powerful library. Please also refer to Learn RxJS as a good source to dig deeper into the topic.

Previous

RxJS Operators