juliancadi
juliancadi

Reputation: 1024

RxSwift: Chain Completable to Observable

I'd like to chain a Completable to an observable element. After calling flatMap, onCompleted and onError callbacks don't seem to be called on subscription.

var user = PublishRelay<User>()

func fetchUserInformation(_ userId: String) -> Completable {
    return Completable.create { observer in
        apiService.fetchInformation(for: userId, completion: { response in
            if let name = response?.name {
                user.accept(User(name: name))
                observer(.completed)
            } else {
                observer(.error(ServiceError.userInformation))
            }
        })
        return Disposables.create()
    }
}

login()
.flatMap{ userId in fetchUserInformation(userId) }
.subscribe(
    onCompleted: {
        print("Success!") // Not being called at all
    },
    onError: { error in
        print(error)  // Not being called at all
    }
).disposed(by: disposeBag)

Although fetchUserInformation and observer(.completed) are being called and user information is being successfully fetched, I won't be able to catch onCompleted on subscription (only when preceded by flatMap).

Is there a clean way to achieve this?

Already tried .materialized() just after the flatMap call in order to get an

    Observable<Event<Never>>

rather than a

    Observable<Never>

It doesn't work either.

Upvotes: 7

Views: 13887

Answers (3)

Shai Mishali
Shai Mishali

Reputation: 9382

The correct solution would be using the ‘andThen’ operator.

someCompletable
   .andThen(someObservable) 

Edit: Just read the rest of your code - I'm not sure why you use a Completable at all since it seems you are actually returning some element from that stream.

You'll probably want to use a Single or Plain-ol' observable to relay that value without using an external Relay.

Upvotes: 26

davebcn87
davebcn87

Reputation: 859

I think that you can do something like this:

login()
    .flatMap{ userId -> Observable<Void> in
        return fetchUserInformation(userId).andThen(.just(Void()))
    }.subscribe(onNext: { _ in
        ...
    }).disposed(by: disposeBag)

Upvotes: 7

Nour
Nour

Reputation: 122

As far as I know you can't convert Completable to Observable since the later omits values while Completable does not.

I guess flatMap is returning Observables from Login and then you convert it to Completables and that's why it fails

Upvotes: 0

Related Questions