Skip to content
  • Home
  • Code
  • iOS & Swift
  • Combine
  • RxSwift
  • SwiftUI
  • Flutter & Dart
  • Tutorials
  • Art
  • Blog
Fx Studio
  • Home
  • Code
  • iOS & Swift
  • Combine
  • RxSwift
  • SwiftUI
  • Flutter & Dart
  • Tutorials
  • Art
  • Blog
Written by chuotfx on September 13, 2020

RxSwift – Replay Subjects

RxSwift

Contents

  • Chuẩn bị
  • 1. Khái niệm Replay Subjects
  • 2. Hoạt động
    • 2.1. Create Replay Subjects
    • 2.2. Emit
    • 2.3. Subscribe
    • 2.4. Terminate
    • 2.5. Demo code
  • Tạm kết

Chào bạn đến với Fx Studio. Bài viết lần này sẽ dẫn bạn tới với một loại Subject mới trong thế giới RxSwift. Đó là Replay Subjects.

Trước tiên, bạn cần phải nắm được các kiến thức sau:

    • RxSwift – Observables
    • RxSwift – Hello Subjects

Đó là 2 phần lý thuyết mà đi theo bạn khá lâu đó. Còn nếu mọi thứ đã ổn rồi thì …

Bắt đầu thôi!

Chuẩn bị

    • Xocde 11
    • Swift 5.x
    • Playground

Vẫn là em Playground huyền thoại. Chúng ta vẫn còn dùng tới nó để demo code cho bài viết này. Bạn chỉ cần tạo mới 1 file Playground từ project mà đã cài đặt ngay từ bài đầu của series. Bạn có thể checkout code lại đây.

1. Khái niệm Replay Subjects

Đầu tiên, chúng ta hay đi sơ qua khái niệm của Replay Subjects là gì với việc mô tả bằng sơ đồ marble.

Vẫn là cái sơ đồ huyền thoại và chúng ta cũng thấy là khá tương đồng với 2 loại Subject trước (Publish & Behavior). Điểm khác biệt là bạn hãy tập trung vào thời điểm sau khi subscribe() lần thứ 2 tới Subject. Khi đó, subscriber nhận được 2 giá trị.

Vậy Replay Subject là gì?

Đây cũng là một loại Subject. Đặc điểm của loại subject này, khi phát đi các giá trị thì đồng thời nó lưu lại các giá trị đó trong bộ đệm của mình. Và khi có một subscriber đăng kí tới, subject này sẽ phát đi các giá trị trong bộ đêm của nó cho subscriber đó.

Ta có các đặc điểm sau của loại Subject này:

  • Khởi tạo bằng kích thước bộ đệm của subject
  • Khi phát đi 1 phần tử thì đồng thời lưu trữ nó vào bộ đệm
  • Khi có subscriber mới tới thì sẽ nhận được toàn bộ phần tử trong bộ đệm

2. Hoạt động

2.1. Create Replay Subjects

Chuyển sang xem code ví dụ cho dễ hiểu hơn nào. Bắt đầu bằng việc khai báo 1 Replay Subject. Bạn hãy tạo thêm 1 file Playground để demo code cho phần này. Hoặc dùng lại ở bài trước cũng được. Không quá nhiều code đâu.

Tạo đối tượng subject mới nào.

let subject = ReplaySubject<String>.create(bufferSize: 2)

Phân tích:

  • Class sử dụng là ReplaySubject
  • Kiểu giá trị được phát đi là String
  • Bộ đệm lưu trữ tối đa là 2 phần tử

Ngoài ra, muốn bộ đệm lưu trữ tất cả các giá trị, thì bạn hãy khởi tạo với hàm sau:

let subject = ReplaySubject<String>.createUnbounded()

Bạn nhớ khai báo thêm túi ra quốc dân để dùng cho các ví dụ tiếp theo sau.

2.2. Emit

    // emit
    subject.onNext("1")
    subject.onNext("2")
    subject.onNext("3")

Vẫn là cách emit truyền thống giống như Publish Subject & Behavior Subject. Bạn chỉ cần gọi toán tử .onNext và truyền giá trị vào. Vậy là xong!

2.3. Subscribe

Giờ chúng ta tiến hành phát đi vài dữ liệu & subscribe lần đầu, để xem các giá trị nhận được là gì? Bạn thêm đoạn subscribe này vào:

    // subcribe 1
    subject
      .subscribe { print("🔵 ", $0) }
      .disposed(by: disposeBag)

Okay, thực thi đoạn code và xem kết quả:

🔵  next(2)
🔵  next(3)

Vì với khai báo bufferSize = 2, nên bộ đệm của subject chỉ chứa được tối đa 2 phần tử. Do đó, không nhận được giá trị 1.

Chúng ta tiếp tục phát & subscribe lần 2 để xem ra sao.

    // emit
    subject.onNext("4")
    
    // subcribe 2
    subject
      .subscribe { print("🔴 ", $0) }
      .disposed(by: disposeBag)

Subscriber 1 sẽ nhận được giá trị 4 và subscriber 2 chỉ nhận được 3 và 4.

🔵  next(2)
🔵  next(3)
🔵  next(4)
🔴  next(3)
🔴  next(4)

Khá là EZ!

2.4. Terminate

Còn với error thì như thế nào. Ta lại tiếp tục ví dụ với emit error và subscribe lần thứ 3

    // error
    subject.onError(MyError.anError)
    
    // subcribe 3
    subject
      .subscribe { print("🟠 ", $0) }
      .disposed(by: disposeBag)

Kết quả ra như sau:

🔵  next(2)
🔵  next(3)
🔵  next(4)
🔴  next(3)
🔴  next(4)
🔵  error(anError)
🔴  error(anError)
🟠  next(3)
🟠  next(4)
🟠  error(anError)

Bạn sẽ thấy subscriber thứ 3 sẽ nhận đầy đủ 2 giá trị trong bộ đêm và kèm theo giá trị error của subject. Ngoài ra, 2 subscriber trước đó vẫn nhận error.

Điều này vô tình gây ra một rắc rối. Khi subject đã kết thúc rồi mà các subscriber vẫn nhận được giá trị trong bộ đệm.

Tiếp tục, với việc dispose luôn subject để xem như thế nào.

    // error
    subject.onError(MyError.anError)
    
    // dispose
    subject.dispose()
    
    // subcribe 3
    subject
      .subscribe { print("🟠 ", $0) }
      .disposed(by: disposeBag)

Tới đây thì kết quả có chút thay đổi.

🔵  next(2)
🔵  next(3)
🔵  next(4)
🔴  next(3)
🔴  next(4)
🔵  error(anError)
🔴  error(anError)
🟠  error(Object `RxSwift.(unknown context at $12d143990).ReplayMany<Swift.String>` was already disposed.)

Đối tượng subscriber thứ 3 không nhận được các dữ liệu từ bộ đệm nữa.

Đó là cách kết thúc đau khổ nhanh nhất, tránh nhiều phiền hà về sau khi bạn muốn Replay Subject không phát lại bất cứ gì cho các subscriber mới.

2.5. Demo code

Cũng hơi dài cho việc hướng dẫn bạn bằng code theo kiểu step by step. Và mời bạn xem lại toàn bộ code để có cái nhìn tổng quát nhất nha. Ahihi!

    let disposeBag = DisposeBag()
    enum MyError: Error {
      case anError
    }
    
    let subject = ReplaySubject<String>.create(bufferSize: 2)
    
    // emit
    subject.onNext("1")
    subject.onNext("2")
    subject.onNext("3")
    
    // subcribe 1
    subject
      .subscribe { print("🔵 ", $0) }
      .disposed(by: disposeBag)
    
    // emit
    subject.onNext("4")
    
    // subcribe 2
    subject
      .subscribe { print("🔴 ", $0) }
      .disposed(by: disposeBag)
    
    // error
    subject.onError(MyError.anError)
    
    // dispose
    subject.dispose()
    
    // subcribe 3
    subject
      .subscribe { print("🟠 ", $0) }
      .disposed(by: disposeBag)

Bạn nhớ test thử việc unlimited bộ đệm của Subject thì như thế nào.

let subject = ReplaySubject<String>.createUnbounded()

 

OKAY! Mình xin kết thúc bài viết này tại đây. Nếu có gì thắc mắc hay góp ý cho mình thì bạn có thể để lại bình luận hoặc gởi email theo trang Contact. Hẹn bạn ở các bài viết sau.

Tạm kết

  • ReplaySubject là subject mà sẽ phát lại các giá trị đã phát cho các subscriber mới đăng kí tới
  • Số lượng của các giá trị phát lại tuỳ thuộc vào các cấu hình bộ đệm lúc khởi tạo subject
  • Ngay cả khi subject phát đi error hay completed thì các subscriber mới vẫn sẽ nhận được đầy đủ các giá trị trong bộ đệm và error hay completed cuối cùng đó.
  • Khi sử dụng toán tử dispose() của subject thì toàn bộ mọi thứ sẽ được xoá hết. Nên các subscriber mới lúc đó sẽ không nhận được gì ngoài error.

 

Cảm ơn bạn đã đọc bài viết này!

FacebookTweetPinYummlyLinkedInPrintEmailShares7
Tags: rxswift
Written by chuotfx

Hãy ngồi xuống, uống miếng bánh và ăn miếng trà. Chúng ta cùng nhau đàm đạo về đời, về code nhóe!

Leave a Reply Cancel reply

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

Donate – Buy me a coffee!

Fan page

Fx Studio

Tags

Actor Advanced Swift AI api AppDistribution autolayout basic ios tutorial blog ci/cd closure collectionview combine concurrency crashlytics dart dart basic dart tour Declarative delegate deploy design pattern fabric fastlane firebase flavor flutter GCD gradients iOS MVVM optional Prompt engineering protocol Python rxswift safearea Swift Swift 5.5 SwiftData SwiftUI SwiftUI Notes tableview testing TravisCI unittest

Recent Posts

  • Role-playing vs. Persona-based Prompting
  • [Swift 6.2] Raw Identifiers – Đặt tên hàm có dấu cách, tại sao không?
  • Vibe Coding là gì?
  • Cách Đọc Sách Lập Trình Nhanh và Hiệu Quả Bằng GEN AI
  • Nỗ Lực – Hành Trình Kiến Tạo Ý Nghĩa Cuộc Sống
  • Ai Sẽ Là Người Fix Bug Khi AI Thống Trị Lập Trình?
  • Thời Đại Của “Dev Tay To” Đã Qua Chưa?
  • Prompt Engineering – Con Đường Để Trở Thành Một Nghề Nghiệp
  • Vấn đề Ảo Giác (hallucination) khi tương tác với Gen AI và cách khắc phục nó qua Prompt
  • Điều Gì Xảy Ra Nếu… Những Người Dệt Mã Trở Thành Những Người Bảo Vệ Cuối Cùng Của Sự Sáng Tạo?

Archives

  • May 2025 (2)
  • April 2025 (1)
  • March 2025 (8)
  • January 2025 (7)
  • December 2024 (4)
  • September 2024 (1)
  • July 2024 (1)
  • June 2024 (1)
  • May 2024 (4)
  • April 2024 (2)
  • March 2024 (5)
  • January 2024 (4)
  • February 2023 (1)
  • January 2023 (2)
  • November 2022 (2)
  • October 2022 (1)
  • September 2022 (5)
  • August 2022 (6)
  • July 2022 (7)
  • June 2022 (8)
  • May 2022 (5)
  • April 2022 (1)
  • March 2022 (3)
  • February 2022 (5)
  • January 2022 (4)
  • December 2021 (6)
  • November 2021 (8)
  • October 2021 (8)
  • September 2021 (8)
  • August 2021 (8)
  • July 2021 (9)
  • June 2021 (8)
  • May 2021 (7)
  • April 2021 (11)
  • March 2021 (12)
  • February 2021 (3)
  • January 2021 (3)
  • December 2020 (3)
  • November 2020 (9)
  • October 2020 (7)
  • September 2020 (17)
  • August 2020 (1)
  • July 2020 (3)
  • June 2020 (1)
  • May 2020 (2)
  • April 2020 (3)
  • March 2020 (20)
  • February 2020 (5)
  • January 2020 (2)
  • December 2019 (12)
  • November 2019 (12)
  • October 2019 (19)
  • September 2019 (17)
  • August 2019 (10)

About me

Education, Mini Game, Digital Art & Life of coders
Contacts:
contacts@fxstudio.dev

Fx Studio

  • Home
  • About me
  • Contact us
  • Mail
  • Privacy Policy
  • Donate
  • Sitemap

Categories

  • Art (1)
  • Blog (44)
  • Code (11)
  • Combine (22)
  • Flutter & Dart (24)
  • iOS & Swift (102)
  • No Category (1)
  • RxSwift (37)
  • SwiftUI (80)
  • Tutorials (87)

Newsletter

Stay up to date with our latest news and posts.
Loading

    Copyright © 2025 Fx Studio - All rights reserved.