如果我们看看你的storeClasses
and storeFeatures
,我们看到他们是not真正返回 Bool 的操作;他们本质上是试图发布一些东西可能会失败。因此你真正想知道的不是东西是否返回true
or false
但无论是否failed。这就是你真正的意思——在编程中,最好说出你的意思.
使用组合框架,我们可以以令人难以置信的简洁来表达这种行为。当我们要同时执行多个异步操作时,这就是合并。如果其中一个失败了整个合并失败。换句话说,你想做的事情实际上是自动的!
例如,想象一下,我们通过将您的后期操作包装在延迟的 Futures 类型中来表达它们<Void,Error>
。假设我们有方法storeClassesFuture
and storeFeaturesFuture
产生这些期货。那么你所要说的就是:
Publishers.Merge(storeClassesFuture(), storeFeaturesFuture())
这就是它的全部内容!如果您订阅了该合并sink
,那么它要么收到一个finished
完成或failure
完成。你猜怎么着?它接收到failure
完成当且仅当一个或两个后操作失败!它接收到finished
仅当他们都成功时才完成,即exactly你想知道什么。
作为测试台,这里是您的示例实现storeInformation
(出于示例的目的,我忽略了字符串):
var storage = Set<AnyCancellable>()
enum Oops : Error { case darn }
func storeInformation() {
Publishers.Merge(storeClassesFuture(), storeFeaturesFuture())
.receive(on: DispatchQueue.main)
.sink { (completion) in
switch completion {
case .failure: print("at least one of them failed")
case .finished: print("they both succeeded")
}
print("---")
} receiveValue: { _ in }
.store(in: &storage)
}
作为随机测试,这里有两个可以随机成功或失败的 future:
func storeClassesFuture() -> AnyPublisher<Void,Error> {
Deferred {
Future<Void,Error> { promise in
if Bool.random() {
print("storeClassesFuture succeeded")
promise(.success(()))
} else {
print("storeClassesFuture failed")
promise(.failure(Oops.darn))
}
}
}.eraseToAnyPublisher()
}
func storeFeaturesFuture() -> AnyPublisher<Void,Error> {
Deferred {
Future<Void,Error> { promise in
if Bool.random() {
print("storeFeaturesFuture succeeded")
promise(.success(()))
} else {
print("storeFeaturesFuture failed")
promise(.failure(Oops.darn))
}
}
}.eraseToAnyPublisher()
}
这是调用的一些示例输出storeInformation
反复:
storeClassesFuture succeeded
storeFeaturesFuture succeeded
they both succeeded
---
storeClassesFuture failed
storeFeaturesFuture failed
at least one of them failed
---
storeClassesFuture failed
storeFeaturesFuture succeeded
at least one of them failed
---
storeClassesFuture failed
storeFeaturesFuture failed
at least one of them failed
---
storeClassesFuture failed
storeFeaturesFuture succeeded
at least one of them failed
---
storeClassesFuture succeeded
storeFeaturesFuture succeeded
they both succeeded
---
storeClassesFuture succeeded
storeFeaturesFuture succeeded
they both succeeded
---
storeClassesFuture failed
storeFeaturesFuture succeeded
at least one of them failed
---
storeClassesFuture failed
storeFeaturesFuture succeeded
at least one of them failed
---
storeClassesFuture succeeded
storeFeaturesFuture succeeded
they both succeeded
---
正如您所看到的,您所追求的逻辑通过两个可失败的 Future 的合并完美地表达了。
(这种事情是采用Combine框架而不是使用DispatchGroup的一个很好的理由。我发现我以前用DispatchGroup做的所有事情都可以用Combine做得更好。这恰好是一个特别明确的实例。)