在 RxSwift 中处理嵌套的可观察对象
handle nested observables in RxSwift
我正在尝试将 facebook 登录与 rest 调用结合起来,因此当用户登录时,它应该对服务器进行身份验证调用,服务器在其中进行图形调用,但是我有点困惑我如何使用 RxSwift 嵌套调用?到目前为止,我有一个 FacebookProvider class,方法如下
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()
})
}
您将要使用 flatMap
传递给 flatMap
的闭包将 return 一个可观察对象。 flatMap
然后会处理取消嵌套,这意味着如果闭包 return 是一个 Observable<T>
类型的值,并且您在 [=18] 类型的值上调用 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)
}
在viewController
facebookProvider.validate().flatMap { [weak self] token in
return self?.loginViewModel.retrieveUserData(token: token)
}.subscribe { event in
switch event {
// ...
}
}.addDisposableTo(disposeBag)
我正在尝试将 facebook 登录与 rest 调用结合起来,因此当用户登录时,它应该对服务器进行身份验证调用,服务器在其中进行图形调用,但是我有点困惑我如何使用 RxSwift 嵌套调用?到目前为止,我有一个 FacebookProvider class,方法如下
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()
})
}
您将要使用 flatMap
传递给 flatMap
的闭包将 return 一个可观察对象。 flatMap
然后会处理取消嵌套,这意味着如果闭包 return 是一个 Observable<T>
类型的值,并且您在 [=18] 类型的值上调用 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)
}
在viewController
facebookProvider.validate().flatMap { [weak self] token in
return self?.loginViewModel.retrieveUserData(token: token)
}.subscribe { event in
switch event {
// ...
}
}.addDisposableTo(disposeBag)