Angular RxJS and Observable Tutorial with Real-World Examples

by Didin J. on May 27, 2025 Angular RxJS and Observable Tutorial with Real-World Examples

Learn how to use RxJS Observables in Angular with practical examples. Master async data streams, operators, and subscriptions in Angular apps

Working with asynchronous data is a core part of building modern web applications. In Angular, RxJS Observables provide a powerful way to handle async data streams—whether you're dealing with HTTP requests, user events, or real-time updates.

In this tutorial, you'll learn how to use RxJS Observables in Angular, including how to create and subscribe to Observables, use common RxJS operators, and apply best practices for managing asynchronous data. We’ll walk through practical examples that demonstrate how Observables can simplify complex workflows in Angular applications.


Preparation: Installing Angular CLI and Creating the App

Before diving into RxJS and Observables in Angular, make sure you have the Angular CLI installed. If you haven't already, install it globally using the following command:

npm install -g @angular/cli

Next, create a new Angular application:

ng new angular-observable-rxjs

During the setup, Angular CLI will prompt you to:

  • Add Angular routing: Yes

  • Choose a stylesheet format: CSS (or any of your choice)

After the app is created, navigate to the project folder:

cd angular-rxjs-observable

Then, run the development server to confirm everything is working:

ng serve --open

Visit http://localhost:4200 in your browser, you should see the default Angular welcome page.

Now you’re ready to implement RxJS and Observable examples in your Angular app.

Angular RxJS and Observable Tutorial with Real-World Examples - hello


What is an Observable?

An Observable is a key part of RxJS (Reactive Extensions for JavaScript), which is the reactive programming library Angular uses for handling asynchronous operations.

In simple terms, an Observable is a data stream that can emit multiple values over time. You can subscribe to an Observable to receive these values and react to them as they occur, similar to how you’d respond to events like button clicks or API responses.

Think of it as a more powerful and flexible alternative to Promises, especially useful when:

  • You need to handle multiple values over time

  • You want to cancel a subscription (e.g., unsubscribe when a component is destroyed)

  • You need to compose multiple async operations using operators

Observable vs Promise

Feature Observable Promise
Emits multiple values ✅ Yes ❌ No (resolves once)
Lazy execution ✅ Yes (only runs on subscription) ❌ No (executes immediately)
Cancellable ✅ Yes ❌ No
Composable with operators ✅ Yes (via RxJS operators) ⚠️ Limited

In Angular, you’ll most commonly encounter Observables when:

  • Making HTTP requests with HttpClient

  • Listening to form changes via FormControl.valueChanges

  • Subscribing to route parameters or query parameters

  • Managing state and data flow in services

Next, let’s look at how to create and subscribe to Observables in your Angular app.


Creating and Subscribing to Observables in Angular

To work with Observables in Angular, you’ll typically either create your own Observable using RxJS or consume one from Angular’s built-in APIs, like HttpClient, FormControl, or ActivatedRoute.

Creating an Observable

You can create a basic Observable using RxJS's Observable constructor or helper functions like of(), from(), or interval().

Here’s an example using of(), in app.component.ts:

import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { of } from 'rxjs';

const fruits$ = of('Apple', 'Banana', 'Mango');

fruits$.subscribe({
  next: fruit => console.log(fruit),
  complete: () => console.log('All fruits delivered!')
});

@Component({
  selector: 'app-root',
  imports: [RouterOutlet],
  templateUrl: './app.component.html',
  styleUrl: './app.component.scss'
})
export class AppComponent {
  title = 'angular-observable-rxjs';
}

This will output:

Apple
Banana
Mango
All fruits delivered!

Subscribing to an Observable

Subscribing is how you start listening for data from an Observable. Subscriptions typically include:

  • next: handle emitted values

  • error: handle errors

  • complete: handle completion

Here’s an example of using interval() to emit numbers every second:

import { interval } from 'rxjs';

const counter$ = interval(1000);

const subscription = counter$.subscribe(value => {
  console.log(`Timer: ${value}`);
});

// Optionally unsubscribe after 5 seconds
setTimeout(() => {
  subscription.unsubscribe();
  console.log('Unsubscribed');
}, 5000);

This will print:

Timer: 0
Timer: 1
Timer: 2
Timer: 3
Timer: 4
Unsubscribed

Using Observables in Angular Components

Here's a practical example using an Observable in a component with HttpClient:

import { HttpClient } from '@angular/common/http';
import { Component } from '@angular/core';

@Component({
  selector: 'app-data-list',
  imports: [],
  templateUrl: './data-list.component.html',
  styleUrl: './data-list.component.scss'
})
export class DataListComponent {
  items: any[] | undefined;

  constructor(private readonly http: HttpClient) {
    this.http.get<any[]>('https://api.example.com/items')
      .subscribe(data => this.items = data);
  }
}

This makes an HTTP GET request and assigns the returned data to the items property.


Using Observable Operators

RxJS operators are powerful tools that let you transform, filter, and combine data streams in a functional style. Angular developers commonly use operators to manipulate data before it reaches the component.

Operators are used with the pipe() method, which allows you to chain multiple operators together.

Commonly Used Operators

map()

Transforms the emitted values from the source Observable.

import { of } from 'rxjs';
import { map } from rxjs/operators';

of(1, 2, 3)
  .pipe(map(value => value * 2))
  .subscribe(result => console.log(result)); // Output: 2, 4, 6

filter()

Filters the values emitted by an Observable based on a condition.

import { of } from 'rxjs';
import { filter } from 'rxjs/operators';

of(1, 2, 3, 4, 5)
  .pipe(filter(value => value % 2 === 0))
  .subscribe(result => console.log(result)); // Output: 2, 4

tap()

Used for side effects (like logging) without affecting the stream.

import { of } from 'rxjs';
import { tap } from 'rxjs/operators';

of('A', 'B', 'C')
  .pipe(tap(value => console.log(`Processing: ${value}`)))
  .subscribe();

switchMap()

Switches to a new Observable on each emission, canceling the previous one. Often used with HTTP requests.

import { Component } from '@angular/core';
import { FormControl } from '@angular/forms';
import { debounceTime, switchMap } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-search',
  template: `<input [formControl]="searchControl" placeholder="Search">`
})
export class SearchComponent {
  searchControl = new FormControl();

  constructor(private http: HttpClient) {
    this.searchControl.valueChanges
      .pipe(
        debounceTime(300),
        switchMap(query => this.http.get(`https://api.example.com/search?q=${query}`))
      )
      .subscribe(results => console.log(results));
  }
}

Chaining Operators

You can chain multiple operators to create powerful data pipelines:

import { fromEvent } from 'rxjs';
import { map, filter, debounceTime } from 'rxjs/operators';

fromEvent(document, 'click')
  .pipe(
    debounceTime(200),
    map((event: any) => event.clientX),
    filter(x => x > 300)
  )
  .subscribe(x => console.log(`Click at X: ${x}`));


Handling HTTP Requests with Observables

Angular's HttpClient Service uses Observables under the hood, making it easy to work with asynchronous data from REST APIs. When you send an HTTP request, Angular returns an Observable, allowing you to subscribe and handle the response.

Importing HttpClientModule

Before using HttpClient, import HttpClientModule in your app.config.ts (or app.module.ts If you're still using modules):

import { provideHttpClient } from '@angular/common/http';

export const appConfig: ApplicationConfig = {
  providers: [provideHttpClient()],
};

Making a GET Request

Use the HttpClient.get() method to retrieve data from a REST API.

import { Component, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-posts',
  standalone: true,
  template: `
    <h2>Posts</h2>
    <ul>
      <li *ngFor="let post of posts">{{ post.title }}</li>
    </ul>
  `
})
export class PostsComponent {
  private http = inject(HttpClient);
  posts: any[] = [];

  ngOnInit() {
    this.http.get<any[]>('https://jsonplaceholder.typicode.com/posts')
      .subscribe(data => this.posts = data);
  }
}

Handling Errors

Use the catchError operator to gracefully handle HTTP errors.

import { catchError } from 'rxjs/operators';
import { of } from 'rxjs';

this.http.get<any[]>('https://jsonplaceholder.typicode.com/posts')
  .pipe(
    catchError(error => {
      console.error('Error fetching posts', error);
      return of([]);
    })
  )
  .subscribe(data => this.posts = data);

Posting Data

You can also send data using post(), put(), or delete() methods:

this.http.post('https://jsonplaceholder.typicode.com/posts', {
  title: 'New Post',
  body: 'This is the content.',
  userId: 1
}).subscribe(response => console.log(response));


Subjects and Multicasting Observables

While standard Observables are unicast (each subscription receives a separate execution), Subjects are multicast — meaning they allow multiple subscribers to share the same Observable execution. Subjects are both an Observable and an Observer, making them powerful for event sharing and state broadcasting.

Creating a Subject

To create a Subject, import it from rxjs:

import { Subject } from 'rxjs';

const subject = new Subject<number>();

Emitting Values​​​​​​​

You can manually emit values using subject.next(value):

subject.next(1);
subject.next(2);

Subscribing to a Subject

Multiple subscribers will receive the same values emitted from the Subject:

subject.subscribe(value => console.log('Subscriber A:', value));
subject.subscribe(value => console.log('Subscriber B:', value));

subject.next(100);
// Output:
// Subscriber A: 100
// Subscriber B: 100

Use Case: Component Communication

Subjects are often used for cross-component communication or sharing data streams between services and components.

Example: Shared Service Using Subject

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class MessageService {
  private messageSubject = new Subject<string>();
  message$ = this.messageSubject.asObservable();

  sendMessage(message: string) {
    this.messageSubject.next(message);
  }
}

Sending and Receiving Messages in Components

Sender Component:

constructor(private messageService: MessageService) {}

send() {
  this.messageService.sendMessage('Hello from Sender!');
}

Receiver Component:

constructor(private messageService: MessageService) {}

ngOnInit() {
  this.messageService.message$.subscribe(msg => {
    console.log('Received:', msg);
  });
}


Conclusion

In this tutorial, we explored how to effectively use Observables and RxJS in modern Angular applications. You learned the fundamentals of Observables, how to create and subscribe to them, use powerful RxJS operators, handle HTTP requests, and utilize Subjects for multicasting and component communication.

Mastering Observables is essential for building reactive and maintainable Angular apps. With RxJS, you can streamline asynchronous operations, improve code clarity, and enhance the user experience through responsive UI updates.

As Angular continues to evolve, reactive programming remains a core concept. Keep experimenting with more advanced operators like mergeMap, switchMap, concatMap, and combineLatest to unlock even more powerful patterns in your projects.

You can get the full source code from our GitHub.

If you don’t want to waste your time designing your front-end or your budget to spend by hiring a web designer, then Angular Templates is the best place to go. So, speed up your front-end web development with premium Angular templates. Choose your template for your front-end project here.

That's just the basics. If you need more deep learning about MEAN Stack, Angular, and Node.js, you can take the following cheap course:

Thanks!