【发布时间】:2017-08-25 02:02:15
【问题描述】:
我正在尝试组合 observables,并且我希望它们按顺序运行(例如,执行步骤 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()
}
}
【问题讨论】:
-
作为一般规则,除非您正在构建库/框架,否则不应使用“Observable.create()”。其次,你的‘Observable’只发出一个‘onNext’事件,那么为什么不用‘Single’而不是‘Observable’呢?您能否说明您打算如何使用这些可观察对象?因为你似乎在尝试解决一个你一开始就不应该遇到的问题。
-
为什么不使用
Observable.create()是“一般规则”?我有服务外观,我想返回 observables 而不是使用闭包。这似乎是 RxSwift 的常见模式。我在哪里可以阅读有关此规则的更多信息?我不知道Single,所以这很有帮助。 -
基本上,因为它是更多的工作。在像您这样的简单情况下,首选的解决方案是使用“.just()”或“.from()”。对于服务外观,最好使用 '.switchEmpty()'、'.retryError()'、'.catchErrorJustReturn()' 和我个人最喜欢的 '.switchLatest()'
标签: conditional observable rx-swift