Sử dụng Subjects và BehaviorSubjects trong Angular

8 min read

Giới thiệu về Subjects và BehaviorSubjects:

Chào các dev, hôm nay chúng ta sẽ thảo luận về Subjects và BehaviorSubjects. Chúng đóng vai trò quan trọng trong việc chia sẻ dữ liệu một cách mượt mà trong ứng dụng.

Lĩnh vực phát triển web đã trải qua sự phát triển đáng kể và người dùng ngày nay mong đợi những ứng dụng tương tác và phản hồi mạnh mẽ. Angular là một công cụ hữu ích giúp các nhà phát triển đáp ứng những kỳ vọng này. Một phần lớn sự hỗ trợ này đến từ cách Angular xử lý dữ liệu bằng cách sử dụng Subjects và BehaviorSubjects.

Trong các phần tiếp theo, chúng ta sẽ tìm hiểu Subjects và BehaviorSubjects hơn, thấy cách chúng hoạt động qua ví dụ.

Về Observables:

Subjects đóng một vai trò quan trọng trong việc đảm bảo luồng dữ liệu mượt mà trên toàn ứng dụng của bạn. Trước khi nói về Subjects, điều quan trọng là nắm vững cơ bản về Observables và Observers, vì Subjects là một phần mở rộng của các khái niệm này.

Observables giống như các đài phát thanh, phát sóng dữ liệu, trong khi Observers giống như người nghe đài, được điều chỉnh để nhận dữ liệu này. Trong Angular, Observables phát ra luồng dữ liệu và Observers subscribe nhận luồng này, phản ứng với dữ liệu mới nếu có.

Về Subjects:

Sau khi có một hiểu biết sơ bộ về Observables, hãy tưởng tượng một tình huống trong đó bạn muốn chia sẻ một nguồn dữ liệu duy nhất giữa nhiều phần của ứng dụng của bạn. Đây là lúc Subjects xuất hiện. Subjects là một loại đặc biệt của Observables có khả năng truyền dữ liệu đến nhiều Observers cùng một lúc. Chúng đảm bảo rằng tất cả subscribers chia sẻ cùng một luồng dữ liệu, thúc đẩy tính nhất quán dữ liệu thời gian thực trong ứng dụng của bạn.

subjects

Multicasting:

Multicasting là một khía cạnh quan trọng trong việc quản lý luồng dữ liệu. Được hiểu đơn giản, nó liên quan đến việc chia sẻ một tín hiệu dữ liệu duy nhất với nhiều người theo dõi.

Khác với mô hình unicast, mà mỗi người theo dõi sẽ nhận một phiên bản độc lập của luồng dữ liệu, multicasting đảm bảo rằng tất cả các observers sẽ chia sẻ cùng một luồng dữ liệu.

Điều này trở nên đặc biệt hữu ích khi bạn phải đảm bảo rằng nhiều phần khác nhau trong ứng dụng của bạn cần phản ứng hoặc xử lý cùng một luồng dữ liệu trong thời gian thực.

Về mặt ngữ cảnh của Subjects trong Angular, việc multicasting là một khả năng tự nhiên. Khi một Subject phát ra một giá trị dữ liệu mới, giá trị này được gửi đến tất cả subscribers cùng một lúc. Tính chia sẻ này về dữ liệu giúp thúc đẩy tính nhất quán dữ liệu thời gian thực trên nhiều phần khác nhau của ứng dụng, đảm bảo rằng mọi subscribers nhận và xử lý cùng dữ liệu.

Ví dụ:

import { Subject } from 'rxjs';

// Create a new Subject
const mySubject = new Subject<number>();

// Subscribe two observers to the Subject
mySubject.subscribe(value => {
  console.log(`Observer 1 received: ${value}`);
});

mySubject.subscribe(value => {
  console.log(`Observer 2 received: ${value}`);
});

// Emit values through the Subject
mySubject.next(10);
mySubject.next(20);

Bạn sẽ thấy được output:

Trong ví dụ này, chúng tôi tạo một Subject có tên là mySubject. Sau đó, chúng tôi subscribe hai observers vào mySubject. Khi chúng tôi emit các giá trị bằng cách sử dụng mySubject.next(value), cả hai observers đều nhận các giá trị phát ra đồng thời. Điều này thể hiện tính chất “multicasting” của Subjects.

Khái niệm về Observables “Hot”:

Khái niệm về Observables “hot” và “cold” là cốt lõi trong việc hiểu cách luồng dữ liệu hoạt động trong reactive programming.

  • Observables “Cold”: Một observable “cold” bắt đầu emit dữ liệu chỉ khi nó có subscriber. Mỗi subscriber nhận một bản thực hiện độc lập của observable, có nghĩa là luồng dữ liệu được bắt đầu lại cho mỗi subscriber.
  • Observables “Hot”: Ngược lại, observables “hot” bắt đầu phát ra dữ liệu ngay sau khi chúng được tạo, bất kể có subscriber hay không. Dữ liệu được phát ra theo thời gian thực và bất kỳ subscriber nào kết vào một observable “hot” sẽ nhận dữ liệu từ thời điểm subscribe trở đi. Họ không nhận dữ liệu đã được emit trước khi subscribe. Chúng ta hãy thực hành cả hai, observables “hot” và “cold”, trong các ví dụ thực tế.
// Hot observable example

import { Subject } from 'rxjs';

// Create a new Subject
const mySubject = new Subject<number>();

// Emit a value before any observer has subscribed
mySubject.next(10);

// Subscribe an observer to the Subject
mySubject.subscribe(value => {
  console.log(`Received: ${value}`);
});

// Emit another value
mySubject.next(20);

output: Received: 20

Trong ví dụ này, thậm chí khi một giá trị được phát ra trước khi bất kỳ observer nào subscribe, observer chỉ nhận giá trị emit sau khi họ subscribe, không phải giá trị đã được emit trước đó. Hành vi này điển hình cho observables “hot”. Chúng hoạt động ngay cả trước khi có subscriber, và dữ liệu được phát ra theo thời gian thực, nhưng subscriber chỉ nhận dữ liệu từ thời điểm họ subscribe trở đi.

// Cold observable example

import { Observable } from 'rxjs';

// Create a cold observable
const coldObservable = new Observable<number>(observer => {
  console.log('Observable execution');
  observer.next(Math.random());
});

// Subscribe observer 1 to the cold observable
coldObservable.subscribe(value => {
  console.log(`Observer 1 received: ${value} (random number)`);
});

// Subscribe observer 2 to the cold observable
coldObservable.subscribe(value => {
  console.log(`Observer 2 received: ${value} (random number)`);
});

output:

Trong ví dụ này, chúng tôi tạo một observable “cold” có tên coldObservable, bắt đầu emit một số ngẫu nhiên chỉ khi một observer subscribe. Sau đó, chúng tôi subscribe hai observers riêng biệt vào coldObservable.

Kết quả cho thấy mỗi observer khởi chạy bản thực hiện của observable một cách độc lập và mỗi observer nhận một số ngẫu nhiên khác nhau. Điều này điển hình cho observables “cold”, trong đó mỗi subscriber  khởi chạy một bản thực hiện mới của observable và nhận một tập hợp giá trị emit riêng biệt.

Hành vi này tương phản hoàn toàn với các observables “hot” (như Subjects), trong đó tất cả observer chia sẻ cùng một bản thực hiện của observable và nhận cùng một giá trị.

Để tóm lại, Subjects được phân loại là observables “hot” bởi vì chúng bắt đầu emit dữ liệu ngay sau khi được tạo.

Điểm đặc trưng này của Subjects đảm bảo rằng dữ liệu được emit theo thời gian thực, làm cho chúng trở thành lựa chọn thích hợp cho các tình huống đòi hỏi xử lý dữ liệu theo thời gian thực, chẳng hạn như cập nhật trực tiếp hoặc hệ thống giám sát thời gian thực.

BehaviorSubjects (BehaviorSubjects):

BehaviorSubject là một loại đặc biệt của Subject, nó đi kèm với tính năng độc đáo là giữ giá trị mới nhất. Tính năng này rất mạnh mẽ và giúp quản lý trạng thái của ứng dụng của bạn một cách hiệu quả.

Khi chúng tôi tạo một BehaviorSubject, chúng tôi bắt đầu với một giá trị ban đầu. Khác với Subjects, BehaviorSubjects ghi nhớ giá trị cuối cùng mà chúng nắm giữ, điều này rất hữu ích.

BehaviorSubjects thích hợp để giữ giá trị và chia sẻ chúng trên nhiều phần khác nhau của một trang web. Khi giá trị thay đổi, BehaviorSubjects đảm bảo rằng mọi phần trang web biết về giá trị mới.

Ví dụ:

import { BehaviorSubject } from 'rxjs';

// Create a BehaviorSubject with a starting value of 0
const behaviorSubject = new BehaviorSubject<number>(0);

// A part of the website subscribes to the BehaviorSubject
behaviorSubject.subscribe(value => {
  console.log(`Part 1 received: ${value}`);
});

// Change the value to 1
behaviorSubject.next(1);

// Another part of the website subscribes
behaviorSubject.subscribe(value => {
  console.log(`Part 2 received: ${value}`);
});

// Change the value to 2
behaviorSubject.next(2);

Output:

Hãy phân tích chi tiết

  1. Chúng ta tạo một BehaviorSubject với giá trị khởi đầu là 0.
  2. Part 1 subscribe BehaviorSubject và nhận giá trị là 0.
  3. Ta thay đổi giá trị thành 1, Part 1 biết về điều này.
  4. Khi Part 2 của trang web subscribe, nó ngay lập tức biết giá trị là 1.
  5. Khi chúng ta thay đổi giá trị thành 2, cả hai phần đều biết về điều này.

Điều này cho thấy cách BehaviorSubjects chia sẻ giá trị qua các phần khác nhau của một trang web.

So Sánh Subjects và BehaviorSubjects

Trong Angular, Subjects và BehaviorSubjects là các công cụ giúp chúng tôi quản lý và chia sẻ dữ liệu trong ứng dụng của chúng tôi. Mặc dù chúng có vẻ tương tự, nhưng chúng có một số khác biệt. Hãy nói về những khác biệt này một cách đơn giản và xem khi nào nên sử dụng công cụ nào.

  • Subjects: Lý tưởng cho các tình huống yêu cầu multicast nhưng không cần giá trị ban đầu hoặc ghi nhớ giá trị đã emit cuối cùng. Subjects đơn giản và phù hợp để xử lý sự kiện hoặc thông báo multicast.
  • BehaviorSubjects: Hoàn hảo cho mục đích quản lý trạng thái khi trạng thái ban đầu quan trọng hoặc bất cứ khi nào bạn cần đảm bảo subscribers mới nhận giá trị đã emit cuối cùng. Chúng rất hữu ích khi một phần của ứng dụng của bạn cần cập nhật liên tục với giá trị hiện tại.

Kết luận
Tóm lại, chúng tôi đã tìm hiểu về hai công cụ hữu ích trong Angular: Subjects và BehaviorSubjects.

  • Subjects: Chúng giúp chia sẻ dữ liệu một cách nhanh chóng với nhiều phần của ứng dụng của bạn cùng một lúc.
  • BehaviorSubjects: Chúng cũng làm điều tương tự, nhưng còn ghi nhớ giá trị đã chia sẻ cuối cùng, điều này rất hữu ích trong nhiều tình huống.

Các công cụ này rất hữu ích để đảm bảo ứng dụng của bạn hoạt động một cách mượt mà và giữ dữ liệu được tổ chức. Có rất nhiều thứ bạn có thể làm với Subjects và BehaviorSubjects trong Angular và sử dụng chúng có thể làm cho việc xử lý dữ liệu trong ứng dụng của bạn dễ dàng hơn nhiều. Chúc bạn lập trình vui vẻ!

Bài viết được dịch và phát triển từ bài của tác giả Maria Zayed trên dev

Avatar photo

Leave a Reply

Your email address will not be published. Required fields are marked *