RxJS và Observables trong Angular

Tạo bởi Hoàng Vũ, chỉnh sửa cuối lúc 19 tháng 3, 2025

Trong Angular, RxJS (Reactive Extensions for JavaScript) là một thư viện mạnh mẽ giúp quản lý dữ liệu bất đồng bộ, xử lý sự kiện theo phong cách lập trình reactive.

Mục tiêu bài học:

  • Hiểu RxJSObservables là gì.
  • Biết cách sử dụng các toán tử phổ biến như map, filter, debounceTime để xử lý dữ liệu.
  • Sử dụng Observable để quản lý dữ liệu bất đồng bộ trong Angular.
  • Hiểu và sử dụng SubjectBehaviorSubject để chia sẻ dữ liệu giữa các thành phần trong ứng dụng.

RxJS và Observables

1. Giới thiệu về RxJS và Observables

RxJS là gì?

RxJS (Reactive Extensions for JavaScript) là một thư viện giúp lập trình bất đồng bộ theo mô hình streams.

  • Lập trình bất đồng bộ truyền thống (Promise, Callback) khó quản lý khi có nhiều thao tác nối tiếp.
  • RxJS giúp xử lý dữ liệu bất đồng bộ một cách linh hoạt và dễ bảo trì hơn.
  • Observable trong RxJS là một cách để đại diện cho luồng dữ liệu (stream) có thể phát sinh nhiều giá trị theo thời gian.

Ví dụ về Observable đơn giản:

import { Observable } from 'rxjs';

const observable = new Observable(observer => {
  observer.next('Dữ liệu 1');
  observer.next('Dữ liệu 2');
  setTimeout(() => {
    observer.next('Dữ liệu 3');
    observer.complete();
  }, 2000);
});

observable.subscribe(value => console.log(value));

Khi chạy, console sẽ hiển thị:

Dữ liệu 1
Dữ liệu 2
Dữ liệu 3 (sau 2 giây)

2. Các toán tử phổ biến của RxJS

RxJS cung cấp nhiều toán tử mạnh mẽ giúp xử lý dữ liệu bất đồng bộ dễ dàng.

Toán tử Chức năng
map() Biến đổi từng giá trị trong Observable
filter() Lọc giá trị dựa trên điều kiện
debounceTime() Trì hoãn giá trị phát ra (thường dùng trong tìm kiếm)
switchMap() Hủy bỏ Observable trước đó khi có giá trị mới
mergeMap() Kết hợp nhiều Observable chạy song song
catchError() Xử lý lỗi trong Observable

Ví dụ sử dụng mapfilter:

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

of(1, 2, 3, 4, 5)
  .pipe(
    filter(value => value % 2 !== 0), // Chỉ lấy số lẻ
    map(value => value * 10) // Nhân 10
  )
  .subscribe(result => console.log(result));

Kết quả:

10
30
50

3. Sử dụng Observable để quản lý dữ liệu bất đồng bộ

Observable với HTTP Request

Trong Angular, HttpClient sử dụng Observable để gửi và nhận dữ liệu từ API.

Bước 1: Cài đặt HttpClientModule trong app.module.ts.

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

@NgModule({
  imports: [HttpClientModule]
})
export class AppModule {}

Bước 2: Tạo một Service sử dụng Observable (data.service.ts).

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class DataService {
  private apiUrl = 'https://jsonplaceholder.typicode.com/posts';

  constructor(private http: HttpClient) {}

  getPosts(): Observable<any> {
    return this.http.get(this.apiUrl);
  }
}

Bước 3: Sử dụng Observable trong Component (app.component.ts).

import { Component, OnInit } from '@angular/core';
import { DataService } from './services/data.service';

@Component({
  selector: 'app-root',
  template: `
    <div *ngFor="let post of posts">
      <h3>{{ post.title }}</h3>
      <p>{{ post.body }}</p>
    </div>
  `,
})
export class AppComponent implements OnInit {
  posts: any[] = [];

  constructor(private dataService: DataService) {}

  ngOnInit() {
    this.dataService.getPosts().subscribe(data => {
      this.posts = data;
    });
  }
}

Dữ liệu từ API được hiển thị trên giao diện.

4. Subject và BehaviorSubject trong Angular

Subject là một loại đặc biệt của Observable giúp phát và chia sẻ dữ liệu giữa các thành phần trong ứng dụng.

Loại Đặc điểm
Subject Phát dữ liệu cho tất cả subscriber nhưng không lưu trạng thái trước đó
BehaviorSubject Luôn lưu giá trị mới nhất và phát lại cho subscriber mới

Sử dụng Subject để chia sẻ dữ liệu giữa các Component

Bước 1: Tạo một shared.service.ts.

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

@Injectable({
  providedIn: 'root',
})
export class SharedService {
  private messageSource = new Subject<string>();
  currentMessage = this.messageSource.asObservable();

  changeMessage(message: string) {
    this.messageSource.next(message);
  }
}

Bước 2: Cập nhật Component gửi dữ liệu (sender.component.ts).

import { Component } from '@angular/core';
import { SharedService } from '../services/shared.service';

@Component({
  selector: 'app-sender',
  template: `<button (click)="sendMessage()">Gửi tin nhắn</button>`,
})
export class SenderComponent {
  constructor(private sharedService: SharedService) {}

  sendMessage() {
    this.sharedService.changeMessage('Xin chào từ SenderComponent!');
  }
}

Bước 3: Cập nhật Component nhận dữ liệu (receiver.component.ts).

import { Component, OnInit } from '@angular/core';
import { SharedService } from '../services/shared.service';

@Component({
  selector: 'app-receiver',
  template: `<p>{{ message }}</p>`,
})
export class ReceiverComponent implements OnInit {
  message: string = '';

  constructor(private sharedService: SharedService) {}

  ngOnInit() {
    this.sharedService.currentMessage.subscribe(msg => {
      this.message = msg;
    });
  }
}

Khi bấm nút, dữ liệu sẽ được cập nhật ngay lập tức giữa các Component.

Kết luận

Nội dung Mô tả
RxJS là gì? Thư viện giúp quản lý dữ liệu bất đồng bộ.
Observable Đại diện cho luồng dữ liệu có thể phát sinh nhiều giá trị theo thời gian.
Các toán tử RxJS map, filter, debounceTime, switchMap, mergeMap, catchError.
Observable trong HTTP Sử dụng HttpClient để lấy dữ liệu từ API.
Subject và BehaviorSubject Chia sẻ dữ liệu giữa các Component trong Angular.
Website Logo

Với hơn 10 năm kinh nghiệm lập trình web và từng làm việc với nhiều framework, ngôn ngữ như PHP, JavaScript, React, jQuery, CSS, HTML, CakePHP, Laravel..., tôi hy vọng những kiến thức được chia sẻ tại đây sẽ hữu ích và thiết thực cho các bạn.

Bình luận

Website Logo

Chào, tôi là Vũ. Đây là blog hướng dẫn lập trình của tôi.

Liên hệ công việc qua email dưới đây.

lhvuctu@gmail.com

Chúng Tôi Trên

Bạn đang muốn học về lập trình website?

Bạn cần nâng cao kiến thức chuyên nghiệp hơn để nâng cao cơ hội nghề nghiệp? Liên hệ