0
0
Lập trình
Hưng Nguyễn Xuân 1
Hưng Nguyễn Xuân 1xuanhungptithcm

Tín hiệu Angular Không Thay Thế Observables: Pull và Push

Đăng vào 7 tháng trước

• 6 phút đọc

Tín hiệu Angular Không Thay Thế Observables: Pull và Push

Gần đây, nhiều nhà phát triển đã cố gắng thay thế RxJS bằng cách tạo ra các "toán tử" riêng cho tín hiệu của Angular. Cách tiếp cận này có thể hiểu được, nhưng nó có thể dẫn đến những lỗi tinh vi. Để tránh điều đó, điều quan trọng là hiểu sự khác biệt giữa hai mô hình phản ứng: PushPull.

Giới thiệu

Trong bài viết này, chúng ta sẽ khám phá hai mô hình phản ứng PushPull, cùng với cách áp dụng chúng trong Angular. Chúng ta sẽ tìm hiểu lý do tại sao một số toán tử hoạt động tốt với tín hiệu và một số khác thì không. Cuối cùng, chúng ta sẽ đưa ra một số mẹo và thực hành tốt nhất để quản lý trạng thái trong ứng dụng Angular của bạn.

Push (Observables): Mỗi Giá Trị Được Đẩy Đều Quan Trọng

Trong mô hình Push, nguồn phát (emitter) là người kiểm soát. Nó phát ra các giá trị vào một luồng "observable", và mỗi giá trị được phát ra tồn tại một cách độc lập. Các giá trị này sau đó được xử lý từng cái một bởi những người đang quan sát chúng.

Ví dụ Thực Tế

Hãy tưởng tượng một dây chuyền sản xuất: mỗi bộ phận đi qua tồn tại độc lập. Nếu bạn đứng dọc theo dây chuyền để quan sát, bạn sẽ thấy mỗi bộ phận đi qua mà không có ngoại lệ. Nếu bạn đến muộn, bạn chỉ đơn giản là đã bỏ lỡ một vài bộ phận đầu tiên. Chúng đã được gửi đi và không chờ đợi bạn.

👉 Mô hình này lý tưởng cho việc quản lý dữ liệu dòng, nơi mỗi giá trị đều quan trọng.

Pull (Signals): Chỉ Giá Trị Cuối Cùng Được Lấy Mới Quan Trọng

Trong mô hình Pull, người tiêu dùng là người kiểm soát. Một giá trị chỉ được quan tâm khi nó được đọc một cách rõ ràng. Người tiêu dùng sẽ "kéo" giá trị khi họ cần nó. Điều này ngụ ý rằng các giá trị tạm thời không được đọc là không liên quan.

Ví dụ Thực Tế

Hãy tưởng tượng một bảng thông tin điện tử tại một nhà ga xe lửa. Nó liên tục được cập nhật, hiển thị thông tin theo thời gian thực về các chuyến tàu. Có thể có hàng chục lần cập nhật mỗi giây, nhưng hành khách chỉ thấy phiên bản cuối cùng được hiển thị khi họ nhìn lên. Các cập nhật trung gian không quan trọng với họ. Chỉ có phiên bản mới nhất của trạng thái bảng là có liên quan.

👉 Tín hiệu do đó rất phù hợp để quản lý trạng thái nơi chỉ phiên bản mới nhất là quan trọng.

Tại Sao Một Số Toán Tử Có Ý Nghĩa và Một Số Khác Thì Không

Sự phân biệt giữa Push và Pull là rất quan trọng để hiểu tại sao một số toán tử hoạt động với tín hiệu và một số khác thì không.

✅ Những Gì Hoạt Động: Hoạt Động Trên Trạng Thái Cuối Cùng

Các toán tử không quan tâm đến lịch sử và chỉ phản ứng với sự thay đổi trong trạng thái cuối cùng sẽ hoạt động tốt với tín hiệu. Ví dụ, toán tử double là hoàn hảo cho một tín hiệu. Nó chỉ cần đọc giá trị hiện tại, nhân nó với hai và trả về kết quả. Nó không cần gì khác.

javascript Copy
const count = signal(2);
const doubledCount = computed(() => count() * 2);
console.log(doubledCount()); // 4

❌ Những Gì Không Hoạt Động: Cần Lịch Sử

Các toán tử như filter hoặc take được thiết kế để làm việc với dữ liệu dòng. Việc điều chỉnh chúng cho tín hiệu là rủi ro. Tại sao?

  • Cái Bẫy filter:
    Hãy tưởng tượng một tín hiệu được khởi tạo với giá trị 1 (const counter = signal(1)) và một tín hiệu kết quả (một computed chẳng hạn) chỉ giữ các số chẵn. Nếu bạn thực hiện counter.set(2), sau đó counter.set(3), thì tín hiệu kết quả sẽ không bao giờ thấy giá trị 2. Thực tế, nếu bạn chỉ kéo giá trị cuối cùng, tín hiệu sẽ chỉ xem xét giá trị cuối cùng, đó là 3 (lẻ), và lọc nó ra. Do đó, kết quả sẽ không bao giờ như bạn mong đợi.

    javascript Copy
    const counter = signal(1);
    const evenCounter = computed(() => {
        const value = counter();
        return isEven(value) ? value : undefined;
    });
    
    counter.set(2);
    counter.set(3);
    console.log(evenCounter()); // undefined => thay vì 2

    Ngược lại, nếu giá trị cuối cùng là 4, bạn sẽ có ấn tượng sai rằng toán tử của bạn đang hoạt động chính xác.

    javascript Copy
    const counter = signal(1);
    const evenCounter = computed(() => {
        const value = counter();
        return isEven(value) ? value : undefined;
    });
    
    counter.set(2);
    counter.set(3);
    counter.set(4);
    console.log(evenCounter()); // 4 => kết quả gây nhầm lẫn
  • Cái Bẫy take:

    Tương tự, với tín hiệu counter được khởi tạo với 1, nếu bạn thực hiện counter.set(2), sau đó counter.set(3), và counter.set(4), một toán tử take(3) chỉ xem xét giá trị cuối cùng (4). Nó sẽ không biết rằng các giá trị 1, 23 đã từng tồn tại. Đối với nó, đây là lần lặp đầu tiên (và duy nhất) của nó.

Tóm Tắt

Tín hiệu được tối ưu hóa cho việc quản lý trạng thái của ứng dụng (mô hình Pull), trong khi RxJS là hoàn hảo cho việc quản lý dữ liệu dòng (mô hình Push).

Trước khi sử dụng một trong hai loại, hãy tự hỏi câu hỏi sau:
"Tôi có cần biết lịch sử của dữ liệu hay chỉ giá trị mới nhất là quan trọng với tôi?"
Nếu chỉ giá trị mới nhất quan trọng, tín hiệu là sự lựa chọn cho bạn. Ngược lại, một observable có thể là giải pháp tốt hơn.

Thực Hành Tốt Nhất

  • Hiểu rõ mô hình phản ứng mà bạn đang làm việc.
  • Sử dụng toán tử phù hợp với mô hình (Push hoặc Pull).
  • Kiểm tra kỹ các giá trị được phát ra và đảm bảo rằng bạn hiểu chúng trước khi áp dụng.

Câu Hỏi Thường Gặp

  1. Tín hiệu là gì?
    Tín hiệu là một cách tiếp cận mới trong Angular để quản lý trạng thái, nơi chỉ giá trị cuối cùng được quan tâm.
  2. RxJS có còn cần thiết không?
    RxJS vẫn là một công cụ mạnh mẽ cho việc quản lý dữ liệu dòng, đặc biệt khi bạn cần theo dõi lịch sử dữ liệu.

Kết Luận

Việc lựa chọn giữa tín hiệu và observable phụ thuộc vào nhu cầu cụ thể của ứng dụng của bạn. Hãy đảm bảo bạn hiểu rõ mục tiêu của mình trước khi quyết định sử dụng công cụ nào. Bằng cách áp dụng những kiến thức này, bạn sẽ nâng cao hiệu quả làm việc của mình trong lập trình Angular. Hãy bắt đầu khám phá và áp dụng ngay hôm nay!

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào