Joakim Sjöstedt
Joakim Sjöstedt

Reputation: 948

Can I flatMap into other streams with completables?

I have several completable rx subscriptions in a stream like this:

viewModel?.setupDoorMode().subscribe(onNext: { shouldConnectToDoor in
    if shouldConnectToDoor {
         self.viewModel?.connectAndOpenDoor().subscribe(onCompleted: {
             self.viewModel?.openOrCloseDoor().subscribe().disposed(by: self.disposeBag)
         }).disposed(by: self.disposeBag)
    } else {
         self.viewModel?.openOrCloseDoor().subscribe().disposed(by: self.disposeBag)
    }
}).disposed(by: disposeBag)

I have the feeling that this can be done in a nicer way, like flatMaping the streams into oneanother. But when I try using flatMap I get the error Type '()' cannot conform to 'ObservableConvertibleType'; only struct/enum/class types can conform to protocols. I'm not too familiar with rx to understand that message. Anyway, is there a way to create a more smooth looking stream rather than three subscriptions in a row?

Upvotes: 0

Views: 363

Answers (1)

Nikita Kukushkin
Nikita Kukushkin

Reputation: 15138

You’re definitely on the right track thinking about flatMap to compose your observables. The thing to note here is that calling .subscribe() returns a Disposable type and calling .disposed(by:) on that disposable returns Void aka () type. You can't compose Voids. You have compose the observables, and THEN you subscribe to the result.

guard let viewModel = viewModel else { return }

// Combine the observables
let doorActionObservable = viewModel
    .setupDoorMode()
    .flatMap { /* mind the retain cycle */ shouldConnectToDoor in
        if shouldConnectToDoor {
            return self.viewModel.connectAndOpenDoor()
        } else {
            return self.viewModel.openOrCloseDoor()
        }
    }

// Subscribe to the the resulting observable
doorActionObservable
    .subscribe()
    .disposed(by: disposeBag)

Upvotes: 1

Related Questions