嗨,中秋快樂,趁這連假好好洗滌平日的疲憊吧!今天要講Error handling operators
為了展示Error handling operators,我們把 API 調整一下
class API {
enum APIError: Error {
case unknown
case invalid
}
func request() -> Single<String> {
return Single.create { (single) -> Disposable in
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
let animals = ["Dog", "Cat", "Lion", "Tiger", "Koala", "Monkey", "Pig", "Chicken", "Penguin", "Wolf"]
let number = Int.random(in: -10..<animals.count)
if number > 0 {
single(.success(animals[number]))
} else if number > -5 {
single(.error(APIError.invalid))
} else {
single(.error(APIError.unknown))
}
}
return Disposables.create()
}
}
}
接著加入一個按鈕,讓button tap事件去跟subject綁定,這樣點下按鈕就會把 Void 元素傳給 subject了,萬事俱備後我們來看第一個operators。
let subject = PublishSubject<Void>()
button.rx.tap.bind(to: subject).disposed(by: disposeBag)
很像Rx版的try catch,定義我們在進行operator時,當catch到.error
事件時,要做出怎樣個反應。像以下範例是透過switch了解是哪種錯誤,再把對應的.error
轉變成!
或是?
元素。
let result = subject
.flatMapLatest { _ in
API().request().asObservable()
.catchError {
let error = $0 as! API.APIError
switch error {
case .unknown:
return .just("?")
case .invalid:
return .just("!")
}
}
.materialize()
}
.share()
result.elements().debug("A").subscribe().disposed(by: disposeBag)
result.errors().debug("B").subscribe().disposed(by: disposeBag)
執行結果
A -> Event next(Chicken)
A -> Event next(Lion)
A -> Event next(Pig)
A -> Event next(?)
A -> Event next(Penguin)
A -> Event next(!)
因為在錯誤後有進行catchError將錯誤轉換元素,所以B不會收到.error
事件囉!
如果不管什麼錯誤,都直接給個預設值,那就可以選擇catchErrorJustReturn
,範例如下
let result = subject
.flatMapLatest { _ in
API().request().asObservable()
.catchErrorJustReturn("!?")
.materialize()
}
.share()
執行結果
A -> Event next(!?)
A -> Event next(Chicken)
今天是快樂連假第一天,所以篇幅稍短(?),明天會繼續Error Handling Operators,明天見