RxErrorHandling

1.0.2

fabianmuecke/RxErrorHandling

What's New

2021-07-08T12:35:14Z

Fixed retryWhen

RxErrorHandling

DO NOT USE IN PRODUCTION

This is a proof of concept, for now, which is neither battle tested nor production ready.

What

RxErrorHandling introduces Treatable traits for RxSwift. These feature Combine-like error handling with the error type of an Rx sequence being part of the signature and enforcing the handling of errors.

I'm very aware that the name is awkward and any suggestions for a better name are very welcome.

Usage in a nutshell

Creating Treatables

Use create function (like for Single or Observable) to create a Treatable or make any ObservableType a Treatable using asTreatable:

enum FooError: Error {
    case foo
    case otherFoo
}

enum BarError: Error {
    case bar
    case otherBar
}

// Use create function
let foo = Treatable<String, FooError>.create { treatable in
    guard precondition else {
        treatable(.completed(.failure(.foo)))
        return
    }

    while whatever {
        guard otherPrecondition else {
            treatable(.completed(.failure(.otherFoo)))
            return
        }
        
        treatable(.next(nextValue))
    }
    treatable(.completed(.finished))
}

// Or asTreatable with error mapping (here: someObservable: Observable<String>)
let bar = someObservable.asTreatable(mapError: { error in
    error as? BarError ?? .otherBar
})

Mapping and combining

Use all known functions from Observable, Single, Signal etc. and additionally use mapError to map or unify error types.

enum CombinedError: Error {
    case foo
    case bar
    case other
}

// Map error types to match, when combining sequences
let merged = Treatable<String, CombinedError>.merge(
    foo.mapError { fooError in 
        switch fooError {
            case .foo: return .foo
            case .otherFoo: return .other
        }
    },
    bar.mapError { barError in 
        switch barError {
            case .bar: return .bar
            case .otherBar: return .other
        }
    }
)

Or map back to an observable for compatibility with e.g. existing libraries.

let someTreat: Treatable<Success, Failure>
let infallibleObservable: Observable<Result<Success, Failure>> = someTreat.asResultObservable()
let fallibleObservable: Observable<Success> = someTreat.asObservable()

Result handling

Use the treat function to handle results:

// Use treat function to handle results
merged.treat(onNext: { value in
    // handle next value
}, onCompleted: { completion in
    switch completion {
    case .failure(.foo): break // handle error
    case .failure(.bar): break // handle error
    case .failure(.other): break // handle error
    case .finished: break // handle success
    }
})

let noErrors: Treatable<Element, Never>
noErrors.treat(myObserver) // just use any ObserverType

let mayHaveErrors: Treatable<Result<Success, Failure>, Failure>
mayHaveErrors.treat(myObserver) // use any ObserverType with Element == Result<Success, Failure>

Available Treatable Traits

  • Treatable
  • TreatableSingle
  • TreatableMaybe
  • TreatableCompletable

Description

  • Swift Tools 5.2.0
View More Packages from this Author

Dependencies

Last updated: Tue Mar 12 2024 14:24:17 GMT-0900 (Hawaii-Aleutian Daylight Time)