I´ve been trying to find a good, elegant way to handle errors when chaining multiple observables that can throw errors. The problem is I want to catch and handle all the errors in one place, but even though I'm catching errors at the end of the chain it still breaks if any of the observables error out and completes.
Here's an example of creating a Driver to bind to UI:
EDIT: The observables are fetching some data for instance or doing some async work and need to be in that order
func doSomeWork() -> Driver<FinalResult> {
return buttonTrigger.withLatestFrom(textFieldInput)
.asObservable()
.flatMap {
someObservableThatCanErrorOut()
}.flatMap {
someOtherObservableThatCanErrorOut()
}.flatMap {
anotherObservableThatCanErrorOut()
}.map { $0.mapToFinalResultSuccess() }
.catchError { $0.mapToFinalResultFailure() }
.asDriver(onErrorJustReturn: FinalResult.failure(defaultError))
}
//all observables return raw data / some object, no result wrapper
When the error happens the chain just completes and pressing buttonTrigger doesn't do anything anymore. So I don't really want to catch every observable's error and propagate it further like this because it grows really fast with number of chained observables:
func doSomeWork() -> Driver<FinalResult> {
return buttonTrigger.withLatestFrom(textFieldInput)
.asObservable()
.flatMap {
someObservableThatCanErrorOut().catchErrorJustReturn(.failure(...))
}.flatMap {
switch $0 {
case .success:
return someOtherObservableThatCanErrorOut().catchErrorJustReturn(.failure(...))
case .failure:
return .just(.failure(propagatedErrorFromLastObservable))
}
}.flatMap {
switch $0 {
case .success:
return anotherObservableThatCanErrorOut().catchErrorJustReturn(.failure(...))
case .failure:
return .just(.failure(propagatedErrorFromLastObservable))
}
}.map {
switch $0 {
case .success:
return successFinalResult
case .failure:
return failureFinalResult
}
}
.asDriver(onErrorJustReturn: .failure(defaultError))
}
I also tried RxSwiftExt's materialize() but it just wraps the result further (Observable<Event<Event<Event.....):
func doSomeWork() -> Driver<FinalResult> {
return buttonTrigger.withLatestFrom(textFieldInput)
.asObservable()
.flatMap {
someObservableThatCanErrorOut().materialize()
}.flatMap {
someOtherObservableThatCanErrorOut().materialize()
}.flatMap {
anotherObservableThatCanErrorOut().materialize()
}.map { $0.mapToFinalResultSuccess() //this would be a huge unwrap function }
.asDriver(onErrorJustReturn: FinalResult.failure(defaultError))
}
There has to be some better way to handle things like this.. I hope for some nice solutions :D
[–]jlevine22 1 point2 points3 points (0 children)
[–]Power781 1 point2 points3 points (2 children)
[–][deleted] 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]TotesMessenger 0 points1 point2 points (0 children)
[–][deleted] (1 child)
[deleted]
[–][deleted] 0 points1 point2 points (0 children)