Reputation:
I am using Facebook to authenticate users. This process happens async. After this is complete i have to authenticate user through firebase, which happens async. Even though I am using RxSwift, I end up nesting async tasks just as if i were to use callbacks and end up with callback hell .
My current procedure just doesn't seem right. Kinda hard to read also. Is it me or is there a more elegant approach to handling multiple async network calls.
for this example I took out the error events because it makes the code even less readable.
Thanks for any tips or guidance.
func rx_login(viewController: UIViewController) {
/// Facebook login
rx_facebookLogin(viewController: viewController)
.asObservable()
.subscribe(onNext: { [weak self] (credentials: AuthCredential, userInfo: [String: Any]) in
/// Firebase Login
rx_firebaseLogin(with: credentials)
.asObservable()
.subscribe(onNext: { [weak self] (uid) in
/// TODO: Save user info firebase db
}).addDisposableTo(disposeBag)
}).addDisposableTo(disposeBag)
Upvotes: 2
Views: 3193
Reputation: 1273
Try using flatMapLatest
:
/// Facebook login
rx_facebookLogin(viewController: viewController)
.flatMapLatest { credentials, _ in rx_firebaseLogin(with: credentials) }
.subscribe(onNext: { [weak self] (uid) in
/// TODO: Save user info firebase db
})
.addDisposableTo(disposeBag)
To handle the errors, you can use map
and filter
, eg.:
let facebookLogin = rx_facebookLogin(viewController: viewController)
.map { credentials, userInfo -> (AuthCredential, String?) in
let error = userInfo["error"] as? String
return (credentials, error)
}
.shareReplayLatestWhileConnected()
// Success
facebookLogin
.filter { _, error in error == nil }
.flatMapLatest { credentials, _ in rx_firebaseLogin(with: credentials) }
.subscribe(onNext: { (uid) in
// Success!
})
.addDisposableTo(disposeBag)
// Fail
facebookLogin
.filter { _, error in error != nil }
.subscribe(onNext: { _, error in
// Error!
print(error)
})
.addDisposableTo(disposeBag)
Upvotes: 2