Contents
Chào bạn đến với Fx Studio. Sau một loạt các bài về Observables trong vũ trụ RxSwift. Thì bài viết này cũng liên quan tới Observable nữa, nhưng cũng có thể xem là một dạng đặc biệt của nó. Đó là Traits.
Để chuẩn bị kiến thức cho bài viết, thì bạn hãy đọc về Observables trước đã. Link mình để phía dưới đây:
Còn bạn đã biết rồi thì …
Bắt đầu thôi!
Chuẩn bị
- Xcode 11
- Swift 5
- Playground
Cũng không phải chuẩn bị gì nhiều ở đây cả. Vẫn là project lần trước và bạn tạo thêm một file Playground là ổn thôi. Nếu bạn quên link checkout source code thì có thể checkout tại đây.
1. Traits
Sống đơn giản cho đời thanh thản.
Đó là phương châm sống mà phần này muốn hướng tới. Thay vì bạn phải cất công create
hay subcribe
đầy đủ các sự kiện mà 1 Observable phát ra. Bạn có thể tạo ra các Observable đặc biệt và đơn thuần thôi. RxSwift gọi là Trait
.
Vậy nó là gì?
- Trait là một wrapper struct với một thuộc tính là một Observable Sequence nằm bên trong nó. Trait có thể được coi như là một sự áp dụng của Builder Pattern cho Observable.
- Để chuyển Trait về thành Observable, chúng ta có thể sử dụng operator
.asObservable()
Tóm gọn, Traits sẽ chỉ thực hiện một nhiệm vụ cụ thể nào đó mà thôi.
struct Single<Element> { let source: Observable<Element> } struct Driver<Element> { let source: Observable<Element> } ...
(code ví dụ mô tả thôi, đừng đè nặng vào đây nha!)
Các đặc điểm của Trait bao gồm:
-
- Nó không xảy ra lỗi.
- Trait được observe và subscribe trên MainScheduler.
- Trait không chia sẻ Side Effect. (một số loại khác sẽ có)
Side Effect là những thay đổi phía bên ngoài của một scope (khối lệnh). Trong RxSwift, Side Effect được dùng để thực hiện một tác vụ nào đó nằm bên ngoài của scope mà không làm ảnh hưởng tới scope đó.
Chúng ta có 2 loại Trait
, một cái cho RxSwift và một cái RxCocoa. Phần Cocoa chúng ta sẽ đề cập ở các bài sau. Còn quay về Traits trong RxSwift thì chúng ta có 3 loại:
-
- Single
- Completable
- Maybe
Giờ đi vào sơ lược từng loại nha! Ahihi
2. Single
- Single là một biến thể của Observable trong RxSwift.
- Thay vì
emit
được ra một chuỗi các element như Observable thì Single sẽ chỉ emit ra duy nhất một element hoặc một error. - Không chia sẻ Side Effect.
Xem code ví dụ sau:
enum FileError: Error { case pathError } let bag = DisposeBag() func readFile(path: String?) -> Single<String> { return Single.create { single -> Disposable in if let path = path { single(.success("Success!")) } else { single(.error(FileError.pathError)) } return Disposables.create() } }
Ta tạo ra 1 enum cho error
và 1 túi rác quốc dân. Sau đó, ta tạo tiếp function readFile
với tham số path
là 1 String Optional.
- Với
path == nil
thì trả vềerror
- Với
path != nil
thì trả vềSuccess!
Function readFile
có giá trí trả về là 1 Single
với kiểu Output là String
. Vì Single cũng là 1 Observable, nên ta lại áp dụng toán tử .create
để tạo. Và quan trọng là handle các thao tác trong đó (lúc nào là error hay giá trị ….)
Sang phần subscribe nó nào!
readFile(path: nil)
.subscribe { event in
switch event {
case .success(let value):
print(value)
case .error(let error):
print(error)
}
}
.disposed(by: bag)
Bạn sẽ thấy, ta sẽ switch ... case
được giá trị mà Single trả về. Với 2 trường hợp.
Ngoài ra, bạn
Có thể biến 1 Observable
thành một Single
bằng toán tử .asSingle()
.
Cuối cùng,
Tới đây, bạn đã thấy được ứng dụng RxSwift vào trong các Model gọi API rồi đó. Cách gọi hay hơn là các call back
.
3. Completable
- Giống với Single, Completable cũng là một biến thể của Observable.
- Điểm khác biệt của Completable so với Single, đó là nó chỉ có thể
emit
ra một error hoặc chỉ complete (không emit ra event mà chỉ terminate). - Không chia sẻ Side Effect.
Ta có một ví dụ giả tưởng như sau:
let bag = DisposeBag() enum FileError: Error { case pathError case failedCaching } func cacheLocally() -> Completable { return Completable.create { completable in // Store some data locally //... //... let success = true guard success else { completable(.error(FileError.failedCaching)) return Disposables.create {} } completable(.completed) return Disposables.create {} } }
Function cacheLocally
trả về một kiểu Completable
. Và áp dụng cách tương tự như Single, thì sử dụng .create
để tạo một Observabe Completable và hành vi cho nó. Cách sử dụng cũng tương tự như trên.
cacheLocally() .subscribe { completable in switch completable { case .completed: print("Completed with no error") case .error(let error): print("Completed with an error: \(error)") } } .disposed(by: bag)
Hoặc cụ thể cho khỏi nhập nhèn với onCompleted
& onError
.
cacheLocally()
.subscribe(onCompleted: {
print("Completed with no error")
},
onError: { error in
print("Completed with an error: \(error)")
})
.disposed(by: bag)
4. MayBe
Đọc qua cái tên của nó, bạn cũng hiểu được ý nghĩa là gì rồi. Đây là thèn ba phải nhiều nhất hội. Vì sao?
- Maybe cũng là một biến thể của Observable và là sự kết hợp giữa Single và Completable.
- Nó có thể emit một element, complete mà không emit ra element hoặc emit ra một error.
Đặc điểm của Maybe:
- Có thể phát ra duy nhất một element, phát ra một error hoặc cũng có thể không phát ra bất cứ event nào và chỉ complete.
- Sau khi thực hiện bất kỳ 1 trong 3 sự kiện nêu trên thì Maybe cũng sẽ terminate.
- Không chia sẻ Side Effect.
Ví dụ thôi:
let bag = DisposeBag() enum MyError: Error { case anError } func generateString() -> Maybe<String> { return Maybe<String>.create { maybe in maybe(.success("RxSwift")) // OR maybe(.completed) // OR maybe(.error(MyError.anError)) return Disposables.create {} } }
Về Maybe
, tương tự như 2 cái trên về cách tạo và xử lý. Nó có thể phát đi cái gì cũng đc, linh hoạt hơn. Dùng cho cách xử lý mà có thể trả không cần phát đi gì cả hoặc kết thúc.
Cách subscribe
như sau:
generateString() .subscribe { maybe in switch maybe { case .success(let element): print("Completed with element \(element)") case .completed: print("Completed with no element") case .error(let error): print("Completed with an error \(error.localizedDescription)") } } .disposed(by: bag)
Hoặc full option như sau:
generateString()
.subscribe(onSuccess: { element in
print("Completed with element \(element)")
}, onError: { error in
print("Completed with an error \(error.localizedDescription)")
}, onCompleted: {
print("Completed with no element")
})
.disposed(by: bag)
Và còn một điều nữa,
Bạn có thể dùng toán tử .asMayBe()
để biến 1 Observable
thành 1 Maybe
.
Tạm kết
- Traits trong RxSwift và RxCocoa có thể xem là các Observable đặc biệt. Chỉ đảm đương vài tính chất hoặc 1 tính chất nào đó
- Trong RxSwift thì bao gồm
- Single
- Completable
- Maybe
- Có thể chuyển đổi từ Observable sequence thành 1 Traits thông 2 toán tử sau:
.asSingle()
.asMaybe()
Tham khảo:
- https://medium.com/swift-india/rxswift-traits-5240965c4f12
- https://github.com/ReactiveX/RxSwift/blob/master/Documentation/Traits.md
Cảm ơn bạn đã đọc bài viết này!
Related Posts:
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!
2 comments
Leave a Reply Cancel reply
Fan page
Tags
Recent Posts
- Charles Proxy – Phần 1 : Giới thiệu, cài đặt và cấu hình
- Complete Concurrency với Swift 6
- 300 Bài code thiếu nhi bằng Python – Ebook
- Builder Pattern trong 10 phút
- Observer Pattern trong 10 phút
- Memento Pattern trong 10 phút
- Strategy Pattern trong 10 phút
- Automatic Reference Counting (ARC) trong 10 phút
- Autoresizing Masks trong 10 phút
- Regular Expression (Regex) trong Swift
You may also like:
Archives
- 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)
anh ơi ngay ở ví dụ 2 chỗ single khi e làm theo ví dụ đó thì trong play ground báo là Type ‘Single’ has no member ‘create’ . Đã import thư viện RxSwift đầy đủ ạ.
Em tạo một iOS Project và cài đặt RxSwift bằng CocoaPod nhóe. Anh mới test lại, thì chạy oke. Còn với Playground thì anh không rõ sao chạy không được nữa. Lâu rồi không mở lên xem lại.