我正在尝试组合observable并且我希望它们按顺序运行(例如,执行步骤1,如果满足某些条件则执行步骤2,如果满足某些条件则执行步骤3)。我发现这样做的唯一方法是为每个步骤添加条件,我不喜欢这个:这是我当前解决方案的一个示例:
enum Status {
case unknown, exists, missing
}
func refresh() -> Observable<Status> {
return checkLocalStatus()
.flatMapLatest { $0 == .exists ? Observable.just($0) : self.attemptRemoteStatusOverride() }
.flatMapLatest { $0 == .exists ? Observable.just($0) : self.attemptRemoteStatusUpdate() }
}
private func checkLocalStatus() -> Observable<Status> {
return Observable.create { observer in
// Regarding Maxim Volgin's comment, here I'm converting a closure to an
// observable... why not use Observable.create?
self.cache.status { (status) in
guard status != .exists else {
observer.onNext(status) // .exists
observer.onCompleted()
}
/* I don't want this condition to be here */
if ignoreRemote {
// status is !exists and we should ignore remote, throw error
observer.onError(Errors.remoteDisabled)
}
observer.onNext(.missing)
observer.onCompleted()
}
}
}
private func attemptRemoteStatusOverride() -> Observable<Status> {
return remote.statusOverride()
}
private func attemptRemoteStatusUpdate() -> Observable<Status> {
return Observable.create { observer in
// Regarding Maxim Volgin's comment, here I'm converting a closure to an
// observable... why not use Observable.create?
self.remote.updateStatus { (status, error) in
guard error == nil else {
observer.onError(error!)
}
observer.onNext(status)
observer.onCompleted()
}
}
}
我想做点什么:
func refresh() -> Observable<Status> {
return checkLocalStatus()
.if({ $0 != .exists && !ignoreRemote },
then: { self.attemptRemoteStatusOverride() },
else: { return $0 })
.if({ $0 != .exists },
then: { self.attemptRemoteStatusUpdate() },
else: { return $0 })
}
或
func refresh() -> Observable<Status> {
return checkLocalStatus()
.flatMapLatest(if: { $0 != .exists && !ignoreRemote }) { self.attemptRemoteStatusOverride() }
.flatMapLatest(if: { $0 != .exists }) { self.attemptRemoteStatusUpdate() }
}
我一直无法找到类似于我正在尝试的东西,所以我认为我错了。有没有人有关于如何结合这种观察结合路线的建议或替代方案?我已经看过使用combineLatest
的示例并根据其他内容的结果返回一些结果,但我想只在条件满足时才执行每个步骤。 combineLatest
将执行每个步骤(每次)然后我将根据其他步骤的输出返回一些步骤的结果。我也开始考虑编写一个自定义操作符,但无法想办法。
更新:我已更改为以下内容并计划编写删除重复的方法:
func refresh() -> Observable<Status> {
return checkLocalStatus()
.flatMapLatest { status -> Observable<Status>
guard status != .exists && !ignoreRemote else {
return Observable.just(status)
}
return self.attemptRemoteStatusOverride()
}
.flatMapLatest { status -> Observable<Status>
guard status != .exists && !ignoreRemote else {
return Observable.just(status)
}
return self.attemptRemoteStatusUpdate()
}
}
答案 0 :(得分:1)
也许你需要某些版本的flatMapLatest函数有条件?你可以使用你想要的语法创建一些你想要的功能:
Any
并使用它
extension Observable {
func flatMapLatest(condition: @escaping (E) -> Bool, then: @escaping (E) -> Observable, otherwise: @escaping () -> Observable) -> Observable {
let observable = self.shareReplayLatestWhileConnected()
let observableCondition = observable.map({ condition($0) }).shareReplayLatestWhileConnected()
let observableThen: Observable<E> = observableCondition
.filter({ $0 })
.withLatestFrom(observable)
.flatMapLatest({ then($0) })
.shareReplayLatestWhileConnected()
let observableOtherwise: Observable<E> = observableCondition
.filter({ !$0 })
.withLatestFrom(observable)
.flatMapLatest({ _ in otherwise() })
.shareReplayLatestWhileConnected()
return Observable<Observable<E>>
.from([observableThen, observableOtherwise])
.merge()
}
}