My sample is create call rest api two observable of result from load rx.request api from moya
func dataOneObservable() -> Observable<ObJectOneClass> {
return myprovider.rx.request(API.loadDataDetail())
.asObservable()
.retry()
.observeOn(MainScheduler.instance)
.filterSuccessfulStatusAndRedirectCodes()
.catchObjectError()
.mapObject(ObJectOneClassResult.self)
.map({ (response) -> ObJectOneClass in
if ObJectOneClass.data != nil {
if let item = response.data {
return item
}
return ObJectOneClass()
}
return ObJectOneClass()
})
}
func dataTwoObservable() -> Observable<ObJectTwoClass> {
return myprovider.rx.request(API.loadDataProfile())
.asObservable()
.retry()
.observeOn(MainScheduler.instance)
.filterSuccessfulStatusAndRedirectCodes()
.catchObjectError()
.mapObject(ObJectTwoClassResult.self)
.map({ (response) -> ObJectTwoClass in
if ObJectTwoClass.data != nil {
if let item = response.data {
return item
}
return ObJectTwoClass()
}
return ObJectTwoClass()
})
}
Then I want to combine result by use combineLastest of RxSwift but when I use .subscribe my response event can't passing result
my function call is same this:
func testCombine(completion:@escaping(_ result:Result<(ObJectOneClass,ObJectTwoClass),Error>) -> ()){
_ = Observable.combineLatest(dataOneObservable(), dataTwoObservable())
.asObservable()
.subscribe({ event in
//Event<(ObJectOneClass,ObJectTwoClass)>
//case .next((a, b)):
switch event{
case .next(response):
completion(.success(response))
case let .error(error):
completion(.failure(error as NSError))
default:
break
}
})
}
please help me guide to syntax completion this.
CodePudding user response:
OK This my topic can fix problem by declare let in .next
func testCombine(completion:@escaping(_ result:Result<(ObJectOneClass,ObJectTwoClass),Error>) -> ()){
_ = Observable.combineLatest(dataOneObservable(), dataTwoObservable())
.asObservable()
.subscribe({ event in
switch event{
case .next((let one,let two)):
completion(.success((one,two)))
case let .error(error):
completion(.failure(error as NSError))
default:
break
}
})
}
CodePudding user response:
Here's an interesting solution:
func testCombineʹ(completion: @escaping(_ result: Result<(ObJectOneClass, ObJectTwoClass), Error>) -> ()) {
_ = Observable.combineLatest(dataOneObservable(), dataTwoObservable())
.map(Result.success)
.catch(combine(Result.failure, Observable.just))
.subscribe(onNext: completion)
}
func combine<A, B, C>(_ f: @escaping (A) -> B, _ g: @escaping (B) -> C) -> (A) -> C {
{ g(f($0)) }
}
That map to Result.success, catch just Result.failure is really common when you are dealing with Result types. It's so common that you might want to make a single operator to capture the notion.
extension Observable {
func toResult() -> Infallible<Result<Element, Error>> {
map(Result.success)
.asInfallible(onErrorRecover: combine(Result.failure, Infallible.just))
}
}