+1

Bài 4. RxSwift – Creating an Observable

Creating an Observable

Bạn cũng đã tạo được Observable bằng 3 toán tử just, of & from. Nhưng đó là các toán tử RxSwift được bọc lại trong các API của ReactiveX. Và đôi khi, bạn chuyển sang Rx cho ngôn ngữ khác lại không thấy chúng nó ở đâu.

Do đó, chúng ta quay về gốc là ReactiveX, thì có 3 cách tạo cơ bản như sau:

  • create
  • just
  • deferred

1. create

Bất cứ khi nào, bạn muốn tạo ra 1 Observable ở bất kì đâu, nó sẽ giúp cho bạn thực hiện được tốt nhất. Toán tử này được dùng rất thường xuyên bởi tính linh hoạt của nó.

Nó sử dụng đưụoc ở tất cả các loại code đồng bộ và bất đồng bộ. Hoặc bạn đặt nó vào 1 function non-Rx cũng không sao. Bạn có thể xác định hành vi cho các việc next, error & completed trong closure của create. Đây là điểm tối quan trọng nhất. Bạn sẽ dùng nó để viết lại logic của 1 function non-Rx thành function Rx.

Cách dùng:

  • Ném cho nó cái closure cho tham số
  • return về 1 Disposables
return Observable.create { observer in 
    return Disposables.create()
}

Ví dụ cho việc sử dụng creater

Tạo 1 function với giá trị trả về là Observable<Void>

    func doAction() -> Observable<Void> {
        return Observable.create { observer in
            self.someAsyncOpertation { success: Bool in
                if success {
                    observer.onNext(()) //It sends a void into the AnyObserver<Void>
                    observer.onCompleted()
                } else {
                    observer.onError(MyError())
                }
            }
            return Disposables.create()
        }
    }

2. just

Giờ tới cái toán tử toán linh hoạt nhất để biến 1 giá trị thành một Observable. Nó được xem là cầu nối cho 2 thế giới : Rx & Non-Rx. Và điều hiển nhiên, Observable mà nó tạo ra sẽ phát đi duy nhất mỗi giá trị kia. Sau đó, Observable sẽ tự kết thúc.

Ngoài just , ta có thêm các toán tử họ hàng của nó như là:

  • empty : không phát gì hết mà kết thúc completed
  • never : không phát ra gì cả. Kể cả error hay completed
  • error : phát ra mỗi error và kết thúc

Ví dụ mới bạn xem tại đây!

3. deferred

Waiting

Với just trên, bạn phóng ngay giá trị đó đi. Nhưng nếu bạn cần phải xử lý dữ liệu trước khi phóng đi. Và nếu như lần nữa, việc xử lý của bạn lại tốn quá nhiều thời gian. Nhất là công việc đó nó sẽ block thread. Thì sẽ có vấn đề lớn xả ra. Ví dụ điển hình là xin phép quyền truy cập tới một số service trong thiết bị:

func permissionObservable() -> Observable<PHAuthorizationStatus> {
    return .just(PHPhotoLibrary.authorizationStatus())
}

Lúc này, sẽ có 1 Alert hiện ra và đợi người dùng cho phép. Rắc rối cũng từ đây mà ra. Rất có thể app của bạn sẽ crash rồi. Vậy tốt nhất là chờ người dùng cho phép rồi hãy emit dữ liệu đi.

Chúng ta giải quyết theo cách dưới đây:

func permissionObservable() -> Observable<PHAuthorizationStatus> {
    return Observable.deferred {
        return .just(PHPhotoLibrary.authorizationStatus())
    }
}

Tác dụng của nó trì hoãn việc phát dữ liệu emit cho subscriber khi đăng kí tới Observable. Vì bạn cũng đã biết rằng Observable sẽ phát dữ liệu ngay khi có 1 subcription tới nó. Và bạn sẽ có đủ thời gian để giải quyết.

Observable factories

Ta bắt đầu xem qua ví dụ sau:

    let bag = DisposeBag()
    
    var flip = true
    
    let factory = Observable<Int>.deferred {
        flip.toggle()
        
        if flip {
            return Observable.of(1)
        } else {
            return Observable.of(0)
        }
    }

Trong đó:

  • flip là cờ lật qua lật lại
  • Nếu flig == true thì trả về 1 Observable với giá trị phát đi là 1
  • Ngược lại là 0 Ở đây, mỗi lần return là 1 Observable mới. Tất nhiên, để làm được việc này, ta sử dụng toán tử .deferred để tạo ra 1 Observable, người ta gọi là Observable factories.

.deferred tạo ra 1 Observable nhưng sẽ trì hoãn nó lại. Và nó sẽ được return trong closure xử lí được gán kèm theo.

Nhìn qua thì Observable factories cũng giống như các Observable bình thường khác. Xem tiếp cách sử dụng của nó:

for _ in 0...10 {
        factory.subscribe(
            onNext: { print($0, terminator: "") })
            .disposed(by: bag)
    
        print()
    }

Kết quả: Lặp từ 0 đến 10, cứ mỗi bước in ra giá trị nhận được:

0
1
0
1
0
1
0
1
0
1
0

Tham khảo: https://fxstudio.dev/rxswift-creating-an-observable/


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí