Search code examples
rx-swift

how to rxswift Observable to value?


I'm currently using RIBs and ReactorKit to bind networking data. The problem here is that the network results come out as Observables, which I have a hard time binding to ReactorKit. Please let me know if there is a way to strip the Observable or turn it into a value. Just like when BehaviorRelay is .value, the value comes out...

    dependency.loadData.getData().flatMap { $0.detailData.flatMap { $0.result }}

====>> Obervable

now what do i do? TT


Solution

  • Please let me know if there is a way to strip the Observable or turn it into a value.

    This is called "leaving" or "breaking" the monad and is a code smell.

    In production code, it is rarely advised to 'break the monad', especially moving from an observable sequence to blocking methods. Switching between asynchronous and synchronous paradigms should be done with caution, as this is a common root cause for concurrency problems such as deadlock and scalability issues.

    -- Intro to Rx

    If you absolutely have to do it, then here is a way:

    class MyClass { 
        private (set) var value: Int = 0
        private let disposeBag = DisposeBag()
    
        init(observable: Observable<Int>) {
            observable
                .subscribe(onNext: { [weak self] new in
                    self?.value = new
                }
                .disposed(by: disposeBag)
        }
    }
    

    With the above, when you query value it will have the last value emitted from the observable. You risk race conditions doing this and that's up to you to deal with.

    That's the direct answer to your question but it isn't the whole story. In ReactorKit, the API call should be made in your reactor's mutate() function. That function returns an Observable<Mutation> so instead of breaking the monad, you should be just mapping the API response into a Mutation which is likely a specific enum case that is then passed into your reduce() function.