Home > database >  How do I combine observe two result rx sequences and subscribe with one closure arguments?
How do I combine observe two result rx sequences and subscribe with one closure arguments?

Time:05-05

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
                    }
                })
        }

Then enter image description here

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))
    }
}
  • Related