简体   繁体   English

rxswift错误处理问题

[英]rxswift error handle issue

I have a BehaviorSubject named createObservable in my view model. 我在视图模型中有一个名为createObservableBehaviorSubject 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)

I have a function named saveObject() also in the view model. 我在视图模型中也有一个名为saveObject()的函数。 If I click the navigation bar right item it will be emitted. 如果我单击右侧导航栏,它将被发出。 And there is an error will send to createObservable 's observer. 并且会向createObservable的观察者发送错误。

func saveObject(){
     ```````
     ```````
    if condition {
        createObservable.on(Event.Next(model))
        createObservable.onCompleted()
    }else{
       createObservable.onError(MyError.someError)
    }
}

The problem is that if the error happened the createObservable will be closed, so I won't receive any Next event in the future. 问题是如果错误发生,createObservable将被关闭,所以我将来不会收到任何Next事件。 I tried to use retry() , but it seems will cause deadlock, view controller can't response any touch event any more. 我试图使用retry() ,但似乎会导致死锁,视图控制器无法再响应任何触摸事件。 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)

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. 我建议创建createObservable类型的PublishSubject<Observable<PassbookModelType>> ,而不是使用BehaviorSubject<PassbookModelType?> ,我猜测,它意外地将两个Rx流在概念上相互分离: saveObject进程本身(一次性进程)和重复启动用户操作启动的saveObject进程。 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)
    }
}

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. 有一个重要的优点:如果一次性进程将来会变成Rx样式(例如,像callbackAfter3sec() -> Observable<Int> ),则无需重新编写使用像上面的viewDidLoad代码。 There is an only one change to do is to pass an Observable<> object to createObservable.onNext(...) . 只有一个更改是将Observable<>对象传递给createObservable.onNext(...)

Sorry for my poor English skill. 抱歉我的英语能力差。 I hope this makes sense to you. 我希望这对你有意义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM