RxJS operations in Angular

Angular, a popular front-end framework, helps to build responsive and scalable applications. At the core of Angular lies RxJS (Reactive Extensions for JavaScript), a powerful library for handling asynchronous operations and event-based programming. In this article, we’ll explore how RxJS helps Angular developers manage complex asynchronous tasks and streamline data flow within their applications.

Prerequisites:

Table of Content

  • What are RxJS Operations?
  • Uses of RxJS operations
  • Common RxJS Operations in Angular
  • Steps to create Angular Project
  • Common RxJS operators

What are RxJS Operations?

In Angular applications, RxJS (Reactive Extensions for JavaScript) is a powerful library used for handling asynchronous and event-based programming using observables. RxJS provides a wide range of operators that enable you to manipulate, transform, combine, and manage observables in a flexible and functional way. These operators make it easier to work with data streams and asynchronous operations in a reactive manner.

Uses of RxJS operations

  • Allows the users to map function to transform the value as given by the observable.
  • Used to collect and combine various observables into one observable.
  • Used to determine the number of values that will be emitted by the observable.
  • Used to tackle or handle the error which is emitted by the observable.
  • Used to filter the data on the basis of some function.
  • Used to determine the time when the values will be emitted by the observables.

Common RxJS Operations in Angular

  1. Observable Creation:
    • of(): Creates an observable that emits a sequence of values.
    • from(): Converts an array, promise, or iterable into an observable.
    • ajax(): Performs an XMLHttpRequest with the provided options and returns an observable.
  2. Combination Operators:
    • merge(): Combines multiple observables into one by merging their emissions.
    • combineLatest(): Combines the latest values from multiple observables into an array or object.
    • forkJoin(): Combines the last values emitted by multiple observables and emits a single value when all observables complete.
  3. Filtering Operators:
    • filter(): Emits only those values from an observable that satisfy a specified condition.
    • distinctUntilChanged(): Emits a value only if it is different from the previous value.
    • debounceTime(): Emits a value from the source observable only after a specified duration has passed without any other value being emitted.
  4. Transformation Operators:
    • map(): Transforms each value emitted by an observable into a new value.
    • pluck(): Extracts the value of a specified property from each emitted object.
    • scan(): Applies an accumulator function to each value emitted by an observable and emits each intermediate result.
  5. Error Handling Operators:
    • catchError(): Handles errors emitted by the source observable and returns a new observable or throws an error.
    • retry(): Resubscribes to the source observable a specified number of times if an error occurs.
  6. Utility Operators:
    • tap(): Performs side effects for each emission on the source observable without modifying the emitted values.
    • delay(): Delays the emissions from the source observable by a specified duration.

Steps to create Angular Project

Step 1: Install Node.js and npm

We need to install Node.js and node package manager to run Angular.

Download node.js from https://nodejs.org/en/download

Step 2: Install Angular CLI

We need to install Angular command Line interface for the creation and management of our Angular projects.

To install Angular CLI, run the following command:

npm install -g @angular/cli

Step 3: Create a New Angular Project:

Now, since we have angular CLI and node.js installed on our system, now we create an Angular project

Type the following command to create a new project

ng new demo-app

Step 4: Go to the Project directory

Now, after creating the project we need to navigate down to the project directory. We can navigate into our project directory with the following command.

cd demo-app

Step 5: Run the application

Since, we have navigated to our project directory, we can run our application with the following command

ng serve

Folder Structure:

Folder Structure


Dependencies:

"dependencies": {
"@angular/animations": "^17.3.0",
"@angular/common": "^17.3.0",
"@angular/compiler": "^17.3.0",
"@angular/core": "^17.3.0",
"@angular/forms": "^17.3.0",
"@angular/platform-browser": "^17.3.0",
"@angular/platform-browser-dynamic": "^17.3.0",
"@angular/router": "^17.3.0",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.3"
}

Common RxJS operators

Here’s an overview of some common RxJS operators and how they can be used in Angular:

1. map

The map operator is used to convert the values emitted by an observable into new values.. This is often used to perform some kind of data transformation.

HTML
<!-- app.component.html -->

<div>
    <h1>Output Data using map operator</h1>
    <ul>
        <li *ngFor="let data of outputData">{{ data }}</li>
    </ul>
</div>
JavaScript
// app.component.ts

import { Component, OnInit } from '@angular/core';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
    outputData: number[] = [];

    ngOnInit() {
        const observable = of(1, 2, 3, 4, 5);

        observable.pipe(
            map(data => data * 2)
        ).subscribe(data => {
            this.outputData.push(data); 
        });
    }
}

Output:

2. filter

The filter operator is used to remove values from an observable depending on a criterion.

HTML
<!-- app.component.html -->

<div>
    <h1>Output Data using filter operator</h1>
    <ul>
        <li *ngFor="let data of outputData">{{ data }}</li>
    </ul>
</div>
JavaScript
// app.component.ts

import { Component, OnInit } from '@angular/core';
import { Observable, of } from 'rxjs';
import { filter } from 'rxjs/operators';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
    outputData: number[] = [];

    ngOnInit() {
        const observable = of(1, 2, 3, 4, 5, 11, 13, 17, 19, 0, 5, 7);

        observable.pipe(
            filter(data => data > 7)
        ).subscribe(data => {
            this.outputData.push(data);
        });
    }
}

Output:

3. mergeMap (flatMap)

The mergeMap operator is used to merge multiple observables into a single observable by applying a function to each emitted value and flattening the resulting observables.

HTML
<!-- app.component.html -->

<div>
    <h1>Output Data using the mergeMap operator</h1>
    <ul>
        <li *ngFor="let data of outputData | async">{{ data }}</li>
    </ul>
</div>
JavaScript
// app.component.ts

import { Component, OnInit } from '@angular/core';
import { Observable, of } from 'rxjs';
import { mergeMap, toArray } from 'rxjs/operators';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
    outputData: Observable<number[]>;

    ngOnInit() {
        const observable = of(1, 2, 3, 4, 5);
        const square = (data: number) => of(data * data);

        this.outputData = observable.pipe(
            mergeMap((data) => {
                return square(data);
            }),

            toArray()
        );
    }
}

Output:

4. combineLatest

The combineLatest operator combines the latest values from multiple observables whenever any of the observables emit a new value.

HTML
<!-- app.component.html -->

<div>
    <h2>combineLatest Example</h2>
    <p>Latest values from observables:</p>
    <ul>
        <li *ngFor="let pair of combinedValues">
            {{ pair[0] }} - {{ pair[1] }}
        </li>
    </ul>
</div>
JavaScript
// app.component.ts

import { Component, OnInit } from '@angular/core';
import { Observable, combineLatest, of } from 'rxjs';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
    combinedValues: [number, string][] = [];

    ngOnInit() {
        const observable1: Observable<number> = of(1, 2, 3, 4);
        const observable2: Observable<string> = of('A', 'B', 'C', 'D');

        const combinedObservable: Observable<[number, string]> = combineLatest(
            observable1,
            observable2
        );

        combinedObservable.subscribe((pair) => {
            this.combinedValues.push(pair);
        });
    }
}

Output: