在 RxSwift 中处理嵌套的 observables
Posted
技术标签:
【中文标题】在 RxSwift 中处理嵌套的 observables【英文标题】:handle nested observables in RxSwift 【发布时间】:2017-01-11 09:47:35 【问题描述】:我正在尝试将 facebook 登录与休息调用相结合,因此当用户登录时,它应该对服务器进行身份验证调用,服务器在其中进行图形调用,但是我对如何进行有点困惑我用 RxSwift 嵌套调用?到目前为止,我有一个带有以下方法的 FacebookProvider 类
func login() -> Observable<String>
return Observable.create( observer in
let loginManager = LoginManager()
//LogOut before
loginManager.logOut()
//Set Login Method
loginManager.loginBehavior = .native
//Login Closure
loginManager.logIn([ .publicProfile, .userFriends, .email], viewController: self.parentController) loginResult in
switch loginResult
case .failed(let error):
print(error)
observer.onError(FacebookError.NoConnection(L10n.networkError))
case .cancelled:
print("User cancelled login.")
case .success(_, let declinedPermissions, let accessToken):
print("Logged in!")
guard declinedPermissions.count > 0 else
observer.onError(FacebookError.DeclinedPermission(L10n.declinedPermission))
return
observer.onNext(accessToken.authenticationToken)
observer.onCompleted()
return Disposables.create()
)
然后我有一个LoginViewModel
与这个模型
public func retrieveUserData() -> Observable<User>
return Network.provider
.request(.auth(fbToken: Globals.facebookToken)).retry(5).debug().mapObject(User.self)
然后我在我的UIViewController
中这样做
facebookProvider.validate().subscribe( [weak self] response in
switch response
case .error(_):
// User is not logged in push to loginController
break
case .next():
//user is logged in retrieveUserData before proceeding
self?.loginViewModel.retrieveUserData().subscribe event in
switch event
case .next(let response):
print(response)
case .error(let error):
print(error)
case .completed:
print("completed")
.addDisposableTo(self?.disposeBag)
break
case .completed:
//data is retrieved and can now push to app
break
).addDisposableTo(disposeBag)
验证
public func rx_validate() -> Observable<String>
return Observable.create( observer in
//Check if AccessToken exist
if AccessToken.current == nil
observer.onError(FacebookError.NotLoggedIn)
else
observer.onNext(Globals.accessToken)
observer.onCompleted()
return Disposables.create()
)
【问题讨论】:
【参考方案1】:你会想要使用flatMap
传递给flatMap
的闭包将返回一个可观察对象。然后flatMap
将负责取消嵌套它,这意味着如果闭包返回Observable<T>
类型的值,并且您在Observable<U>
类型的值上调用flatMap
,则生成的observable 将是Observable<T>
(不是Observable<Observable<T>>
在这种特殊情况下,代码如下所示:
facebookProvider.validate().flatMap [weak self] _ in
return self?.loginViewModel.retrieveUserData()
.subscribe event in
switch event
// ...
.addDisposableTo(disposeBag)
附带说明一下,您可能应该更新 func retrieveUserData()
以接受令牌作为参数,而不是从您的 Globals
结构中获取它。
生成的代码与此类似
public func retrieveUserData(token: String) -> Observable<User>
return Network.provider
.request(.auth(fbToken: token)).retry(5).debug().mapObject(User.self)
在视图控制器中
facebookProvider.validate().flatMap [weak self] token in
return self?.loginViewModel.retrieveUserData(token: token)
.subscribe event in
switch event
// ...
.addDisposableTo(disposeBag)
【讨论】:
这里为什么不用addDisposableTo(disposeBag)
?
只是我的一个遗漏,很抱歉造成混乱。我已经更新了答案。
我已经添加了 validate
函数并进行了较小的名称更改,这只是一个简单的函数检查 AccessToken
是否已经保存,然后将其传递给下一个,但是这给了我以下错误Cannot convert value of type (_) -> Observable<User?> to expected argument type (string) -> O
我已经测试过了,这似乎是[weak self]
的问题,因为删除它可以工作
以及如何在 viewController 中获取 validate()
的订阅事件,因为底部代码似乎没有在 error
、next
和 completed
中打印任何内容。猜这是由于validate()
中的错误事件@以上是关于在 RxSwift 中处理嵌套的 observables的主要内容,如果未能解决你的问题,请参考以下文章