所以基本上我需要执行两个动作:
必须以正确的顺序完成它们,因为如果没有先登录,就无法完成用户配置文件。
所以我有一堆看起来像这样的代码:
func signIn(signinParameters: SignInParameters) -> Observable<SignInResult> {
return Observable<SignInResult>.create { [unowned self] observer in
self.signinParameters = signinParameters
self.apiConnector
.signIn(with: signinParameters)
.do(onNext: { [weak self] signinResult in
self!.apiConnector
.get()
.do(onNext: { user in
let realm = RealmManager.shared.newRealm()!
let realmUser = RealmUser()
realmUser.configure(with: user, in: realm)
try? realm.write {
realm.add(realmUser, update: true)
}
self!.setState(.authenticated)
observer.onNext(signinResult)
}, onError: { (error) in
observer.onError(error)
}, onCompleted: {
observer.onCompleted()
}).subscribe()
}, onError: { error in
observer.onError(error)
}, onCompleted: {
print("completed")
observer.onCompleted()
}).subscribe()
return Disposables.create()
}
我知道这是不对的,因为当两个动作完成时,我无法使用signin结果发送onNext信号。我一直在阅读,我发现我需要对两个动作进行平面映射,将它们组合成一个信号,然后操纵signinresult,但我不知道如何做到这一点。所以任何帮助都会很好。
谢谢
编辑1:
所以我重构代码看起来像这样,但是仍然存在一个问题,即当BOTH操作完成时我无法发送信号,或者我错了?
func signIn(signinParameters: SignInParameters) -> Observable<SignInResult> {
return Observable<SignInResult>.create { [unowned self] observer in
self.signinParameters = signinParameters
self.apiConnector
.signIn(with: signinParameters)
.do(onNext: { (result) in
}, onError: { (error) in
}, onCompleted: {
})
.flatMap({ (result) -> Observable<User> in
self.apiConnector.get().asObservable()
})
.do(onNext: { (user) in
}, onError: { (error) in
}, onCompleted: {
}).subscribe()
return Disposables.create()
}
}
答案 0 :(得分:1)
你的代码不是很干净,很难理解发生了什么(我的意见)。
如果您需要执行两个操作,则可以创建两个函数:
struct Parameters{}
struct Profile{}
struct User{}
func login(parameters: Parameters) -> Observable<User> {
// get user
}
func profile(user: User) -> Observable<Profile> {
// get profile
}
func serial(parameters: Parameters) -> Observable<Profile> {
return login(parameters: parameters).flatMap({ profile(user: $0) })
}
如果需要, login
函数或profile
函数也可以拆分为更小的函数:
func profileStored(user: User) -> Observable<Profile?> {
// get stored profile
}
func profileRequested(user: User) -> Observable<Profile> {
// get profile from network
}
func profile(user: User) -> Observable<Profile> {
let observable = profileStored(user: user)
.shareReplayLatestWhileConnected()
let observableStored = observable
.filter({ $0 != nil })
.map({ $0! })
.shareReplayLatestWhileConnected()
let observableRequested = observable
.filter({ $0 == nil })
.flatMap({ _ in profileRequested(user: user) })
.shareReplayLatestWhileConnected()
return Observable
.of(observableStored, observableRequested)
.merge()
.shareReplayLatestWhileConnected()
}
因此,您可以将较小的函数与flatMap
或任何其他运算符混合使用。
这就是我的方式。希望它会有所帮助