rxswift 错误处理问题 [英] rxswift error handle issue
问题描述
我的视图模型中有一个名为 createObservable
的 BehaviorSubject
.我的视图控制器订阅它.
I have a BehaviorSubject
named createObservable
in my view model. And my view controller subscribe it.
viewModel!.createObservable.subscribe(onNext: {[unowned self] (obj:PassbookModelType?) -> Void in
if let _ = obj{
self.dismissVC()
}
}, onError: { (error) -> Void in
print(error)
}).addDisposableTo(self.dispose)
我在视图模型中有一个名为 saveObject()
的函数.如果我单击导航栏右侧的项目,它将被发出.并且有一个错误会发送给 createObservable
的观察者.
I have a function named saveObject()
also in the view model. If I click the navigation bar right item it will be emitted. And there is an error will send to createObservable
's observer.
func saveObject(){
```````
```````
if condition {
createObservable.on(Event.Next(model))
createObservable.onCompleted()
}else{
createObservable.onError(MyError.someError)
}
}
问题是,如果发生错误,createObservable 将被关闭,因此我将来不会收到任何 Next
事件.我尝试使用 retry()
,但它似乎会导致死锁,视图控制器无法再响应任何触摸事件.那么有人可以告诉我如何解决这个问题吗?非常感谢
The problem is that if the error happened the createObservable will be closed, so I won't receive any Next
event in the future. I tried to use retry()
, but it seems will cause deadlock, view controller can't response any touch event any more. So can some one tell me how to fix this issue? Thanks a lot
viewModel!.createObservable.retry().subscribe(onNext: {[unowned self] (obj:PassbookModelType?) -> Void in
if let _ = obj{
self.dismissVC()
}
}, onError: { (error) -> Void in
print(error)
}).addDisposableTo(self.dispose)
推荐答案
我建议将类型设为 createObservable
PublishSubject
,而不是BehaviorSubject<PassbookModelType?>
,我猜,它意外地将两个概念上彼此分离的 Rx 流压平了:saveObject
过程本身(一个一次性过程)并启动 saveObject
过程由用户反复启动.我写了一个简短的例子来演示它.
I suggest to make the type of createObservable
PublishSubject<Observable<PassbookModelType>>
, instead of BehaviorSubject<PassbookModelType?>
which, I guess, accidentally flattens two Rx streams conceptually separatable each other: the saveObject
process itself (an one-shot process) and starting the saveObject
process initiated by user action repeatedly. I've written a short example to demonstrate it.
let createObservable = PublishSubject<Observable<Int>>()
override func viewDidLoad() {
super.viewDidLoad()
createObservable.flatMap {
$0.map { obj in
print("success: \(obj)")
}
.catchError { err in
print("failure: \(err)")
return empty()
}
}.subscribe()
}
// Simulates an asynchronous proccess to succeed.
@IBAction func testSuccess(sender: UIView!) {
let oneShot = PublishSubject<Int>()
createObservable.onNext(oneShot)
callbackAfter3sec { res in
oneShot.onNext(1)
oneShot.onCompleted()
}
}
// Simulates an asynchronous process to fail.
@IBAction func testFailure(sender: UIView!) {
let oneShot = PublishSubject<Int>()
createObservable.onNext(oneShot)
callbackAfter3sec { res in
oneShot.onError(NSError(domain: "Error", code: 1, userInfo: nil))
}
}
func callbackAfter3sec(completion: Int -> ()) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(NSEC_PER_SEC * 3)), dispatch_get_main_queue()) {
completion(2)
}
}
这有一个重要的优点:如果一次性过程将成为 Rx 风格(例如,像 callbackAfter3sec() -> Observable
),无需像上面的 viewDidLoad
那样重写使用端代码.唯一要做的更改是将 Observable<>
对象传递给 createObservable.onNext(...)
.
There is an important merit with that: If the one-shot process would become in the Rx style (for example, like as callbackAfter3sec() -> Observable<Int>
) in the future, there were no need to re-write the use-side code like in the viewDidLoad
above. There is an only one change to do is to pass an Observable<>
object to createObservable.onNext(...)
.
对不起,我的英语水平很差.我希望这对您有意义.
Sorry for my poor English skill. I hope this makes sense to you.
这篇关于rxswift 错误处理问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!