Swift 使用斯威夫特联合收割机时,切勿在平面图中返回
在RxSwift中,flatMap操作符可以很容易地返回一个不完整的可观测值。假设我们有一条精心设计的愚蠢的可观测链:Swift 使用斯威夫特联合收割机时,切勿在平面图中返回,swift,rx-swift,combine,Swift,Rx Swift,Combine,在RxSwift中,flatMap操作符可以很容易地返回一个不完整的可观测值。假设我们有一条精心设计的愚蠢的可观测链: let repo = DataRepository() Observable .just(Int.random(in: 0 ..< 1000)) .flatMap { num -> Observable<String> in if num == 42 { return .never()
let repo = DataRepository()
Observable
.just(Int.random(in: 0 ..< 1000))
.flatMap { num -> Observable<String> in
if num == 42 {
return .never()
}
return repo
.fetchData()
.filter { $0.statusCode == 200 }
.map { $0.data.title }
}
使用Combine,我能得到的最接近的东西是这样的东西,我还没有尝试编译,但您得到了这样的想法:
Just(Int.random(in: 0 ..< 1000))
.flatMap { num -> AnyPublisher<String, Never> in
if num == 42 {
return Empty<String, Never>(completeImmediately: false).eraseToAnyPublisher()
}
return repo
.fetchData()
.filter { $0.statusCode == 200 }
.map { $0.data.title }
.eraseToAnyPublisher()
}
我同意这个解决方案,但我看到了两个我希望避免的问题:
1联合收割机解决方案在某种程度上更为冗长,以实现相同的目标
2我必须在两个返回的发布服务器上调用eraseToAnyPublisher,否则返回类型不匹配。我相信给出版商打电话会阻止斯威夫特应用一些内部优化,我再也找不到我读过的关于这种优化的文章了;这方面的信息很少
有谁有更好的方法来处理这个示例场景吗?尝试将任何条件逻辑提升到运算符中 在什么条件下,你发出像Observable.never这样的东西,最好在过滤器中捕捉到,这样你就可以免费获得never行为 例如:
Just(Int.random(in: 0 ..< 1000))
.filter { $0 != 42 }
.flatMap {
return repo
.fetchData()
.filter { $0.statusCode == 200 }
.map { $0.data.title }
}
我对DataRepository中的类型了解不够,不知道是否需要在flatMap闭包中键入erase。是的,我意识到这是一个选项,正如我所说,我的示例有点做作。您建议的方法在更高级的用例中不起作用。例如,当您有一个依赖于多个观察值的条件语句时,您不能使用简单的过滤器。在RxSwift中,您可以使用combineLatest并返回一个新的可观测值,或者如果不应发出任何信息,则返回一个“从不”,然后返回一个平面图。这就是我用Combine努力复制的东西,至少在不使用橡皮擦的情况下是这样。你可以在flatMap中使用值,在filter中使用值。我不知道为什么你不能在更高级的用例中使用filter。这样,您就不必在flatMap闭包中创建新的发布服务器,然后键入擦除它,这是您首先要防止的。如果flatMap中的逻辑没有像您提供的示例中那样解析为布尔值,然后使用适当的运算符并将结果平面映射。仅对发布者的输出进行操作,您永远不会进入创建新发布者的业务。在某些情况下,您可能希望这样做,例如,在给定结果上使用flatMap仅发出成功值。我在这里没有找到避免类型擦除的方法,尽管我在flatMap的结果上执行它,而不是在闭包中执行它,闭包仍然比Rx更详细。这是由具体实现构建的联合运算符的结果,Rx将它们隐藏在协议后面,并以这种方式获得类型擦除。没错,任何解析为布尔值的逻辑也可以放在过滤器中。我在评论中的意思是,依赖于多个变量的条件语句可以在CombineTest+flatMap中处理。如果我想在过滤器中应用条件逻辑,我必须做额外的工作:CombineTest必须映射到其参数的元组,过滤器必须执行逻辑,最后调用flatMap来完成通常在flatMap中直接完成的剩余工作。所以这也更冗长/混乱。首先。在这里,返回可观察的。从不是一个非常糟糕的主意。这样做的结果是,您的平面图将永远无法完成。最好是返回Observable.empty.Second,是的,您仍然需要删除任何发布服务器,您说该发布服务器将停止某些内部优化,但这是RxSwift甚至没有提供的优化,因此如果后者的性能可以接受,我相信前者也可以。