iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 11
0
Mobile Development

RxSwift / 30天探索之旅系列 第 11

第 11 天 - Transforming Observables(下)

  • 分享至 

  • xImage
  •  

昨天提到範例中,我們做了一個假的API,他只會回傳.success,但現實情況下,可能會發生.error,這時候會怎樣呢?

我們先修改一下我們的API,他會在兩秒後,隨機決定回傳.success或是.error(APIError.unknown)

class API {

    enum APIError: Error {

        case unknown

    }

    func request() -> Single<Void> {
        .create { (single) -> Disposable in

            DispatchQueue.main.asyncAfter(deadline: .now() + 2) {

                if Bool.random() {
                    single(.success(()))
                } else {
                    single(.error(APIError.unknown))
                }

            }

            return Disposables.create()
        }
    }

}

測試程式我們修改成,用按鈕去觸發API,接著看看成功或失敗會怎樣

let subject = PublishSubject<Void>()

button.rx.tap.bind(to: subject).disposed(by: disposeBag)

let result = subject.flatMapLatest { API().request() }

result
    .debug("A")e
    .subscribe()
    .disposed(by: disposeBag)

執行結果

57:38.535: A -> subscribed
57:43.164: A -> Event next(())
57:52.817: A -> Event next(())
57:56.016: A -> Event error(unknown)
Unhandled error happened: unknown
57:56.017: A -> isDisposed

前兩次都順利成功,但第三次呼叫API發生.error了,接著,因為Observable因收到.error而disposed,後面你再怎麼按鈕他都沒反應,但我們預期是.error可以做錯誤處理,而不是直接銷毀。

materialize

let subject = PublishSubject<Void>()

button.rx.tap.bind(to: subject).disposed(by: disposeBag)

let result = subject.flatMapLatest { API().request().asObservable().materialize() }.share()

result
    .debug("A")
    .subscribe(onNext: {
        if let error = $0.error {
            print("B \(error)")
        }

        if let element = $0.element {
            print("C \(element)")
        }
    })
    .disposed(by: disposeBag)

執行結果

27:40.640: A -> subscribed
7:45.073: A -> Event next(error(unknown))
B unknown
27:47.280: A -> Event next(error(unknown))
B unknown
27:51.220: A -> Event next(next(()))
C ()
27:51.220: A -> Event next(completed)

RxSwift Community

是一個RxSwift的生態系,在這之下有很多RxSwift的專案,今天介紹RxSwiftExt專案下的 materialized+elements.swift ,這是RxSwift的extension,可以把event.elementevent.error轉成Observable,有了這extension,我們的程式能再度進化

let subject = PublishSubject<Void>()

button.rx.tap.bind(to: subject).disposed(by: disposeBag)

let result = subject.flatMapLatest { API().request().asObservable().materialize() }.share()

result.elements().debug("C").subscribe().disposed(by: disposeBag)

result.errors().debug("B").subscribe().disposed(by: disposeBag)

執行結果如下

43:40.168: C -> subscribed
43:40.170: B -> subscribed
43:51.042: C -> Event next(())
43:53.832: B -> Event next(unknown)

這樣寫又更加簡潔清晰,轉化成Observable在後續串連也會更方便!


今天補充了Transforming,明天會接著介紹share,就這樣,掰掰


上一篇
第 10 天 - Transforming Observables (上)
下一篇
第 12 天 - Share & ShareReplay
系列文
RxSwift / 30天探索之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言