Search code examples
swiftpromiserx-swift

How do you sequentially chain observables in concise and readable way


Im new to RXSwift and I've begun investigating how I can perform Promise like function chaining.

I think I'm on the right track by using flatmap but my implementation is very difficult to read so I suspect theres a better way to accomplish it.

What I have here seems to work but I'm getting a headache thinking about what It might looks like if I added another 3 or functions to the chain.

Here Is where I declare my 'promise chain'(hard to read)

LOGIN().flatMap{ (stuff) -> Observable<Int> in
    return API(webSiteData: stuff).flatMap
    { (username) -> Observable<ProfileResult> in
    return accessProfile(userDisplayName: username) }
    }.subscribe(onNext: { event in
        print("The Chain Completed")
        print(event)
    }, onError:{ error in
         print("An error in the chain occurred")
    })

These are the 3 sample functions I'm chaining

struct apicreds
{
    let websocket:String
    let token:String
}
typealias APIResult = String
typealias ProfileResult = Int

// FUNCTION 1
func LOGIN() -> Observable<apicreds> {

    return Observable.create { observer in
        print("IN LOGIn")
        observer.onNext(apicreds(websocket: "the web socket", token: "the token"))
        observer.on(.completed)
        return Disposables.create()
    }
}
// FUNCTION 2
func API(webSiteData: apicreds) -> Observable<APIResult> {

    return Observable.create { observer in
        print("IN API")
        print (webSiteData)
       // observer.onError(myerror.anError)
        observer.on(.next("This is the user name")) // assiging "1" just as an example, you may ignore
        observer.on(.completed)
        return Disposables.create()
    }

}
//FUNCTION 3
func accessProfile(userDisplayName:String)  -> Observable<ProfileResult>
{
    return Observable.create { observer in

        // Place your second server access code
        print("IN Profile")
        print (userDisplayName)

        observer.on(.next(200)) // 200 response from profile call
        observer.on(.completed)
        return Disposables.create()
    }
}

Solution

  • This is a very common problem we run into while chaining operations. As a beginner I had written similar code using RxSwift in my projects as well. And there are two areas of improvement - 1. Refactor the code to remove nested flatMaps 2. Format it differently to make the sequence easier to follow

    LOGIN()
        .flatMap{ (stuff) -> Observable<APIResult> in
            return API(webSiteData: stuff)
        }.flatMap{ (username) -> Observable<ProfileResult> in
            return accessProfile(userDisplayName: username) 
        }.subscribe(onNext: { event in
            print("The Chain Completed")
            print(event)
        }, onError:{ error in
            print("An error in the chain occurred")
        })