调度组逻辑工作流



我正在尝试实现如下DispatchGroup,但是如果第一个调用返回true,则第二个调用返回false,则总体结果将返回false

但是,如果第一个调用返回false,则第二个调用返回true,则总体结果将返回false这不是我预期的。

我想返回false,如果任何呼叫返回false。我该如何处理这个问题?

func storeInformation(id: String?, _ completion: @escaping (Bool) -> ()) {
guard
let id =  id
else {
completion(false)
return
}
let dispatchGroup = DispatchGroup()
var groupResult: Bool = false
dispatchGroup.enter()
storeFeatures { success in
if success {
groupResult = true
} else {
groupResult = false
}
dispatchGroup.leave()
}

dispatchGroup.enter()
storeClasses { success in
if success {
groupResult = true
} else {
groupResult = false
}
dispatchGroup.leave()
}
dispatchGroup.notify(queue: .main) {
completion(groupResult)
}
}
private func storeClasses(_ completion: @escaping(Bool) -> Void) {
postClasses { (error) in
if let _ = error {
completion(false)
} else {
completion(true)
}
}
}
private func storeFeatures(_ completion: @escaping(Bool) -> Void) {
postFeatures { (error) in
if let _ = error {
completion(false)
} else {
completion(true)
}
}
}

如果我们查看您的storeClassesstoreFeatures,我们会发现它们并不是真正返回布尔值的操作;它们本质上是尝试发布可能失败的内容。因此,你真正想知道的不是某物返回truefalse,而是它是否失败。这就是你真正的意思——在编程中,说出你的意思总是更好的。

使用Combine框架,我们可以以令人难以置信的简洁来表达这种行为。当我们有多个异步操作要同时执行时,这就是合并。如果其中一个失败,则整个合并将失败。换句话说,你想做的事情实际上是自动的!

例如,想象一下,我们已经通过将它们包装在<Void,Error>类型的递延期货中来表达您的发布操作。假设我们有产生这些期货的方法storeClassesFuturestoreFeaturesFuture。那么你只能说:

Publishers.Merge(storeClassesFuture(), storeFeaturesFuture())

这就是它的全部内容!如果您订阅该 合并 与sink,则它会收到finished完成或failure完成。你猜怎么着?当且仅当一个或两个发布操作失败时,它才会收到failure完成!只有当它们都成功时,它才会收到finished完成,这正是您想知道的。

作为测试平台,下面是storeInformation的示例实现(出于示例的目的,我忽略了 String):

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)
}

作为随机测试,这里有两个可以随机成功或失败的未来:

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
---

如您所见,您所追求的逻辑通过两个可失败的未来合并得到了完美的表达。

(这种事情是采用 Combine 框架而不是使用 DispatchGroup 的一个很好的理由。我发现我以前在DispatchGroup上所做的一切都可以用Combine做得更好。这恰好是一个特别明确的例子。

这里有一个"AND"语义,所以你应该在你的代码中写它:

let dispatchGroup = DispatchGroup()
var groupResult: Bool = true // identity for AND
dispatchGroup.enter()
storeFeatures { success in
groupResult = groupResult && success // here!
dispatchGroup.leave()
}
dispatchGroup.enter()
storeClasses { success in
groupResult = groupResult && success // and here
dispatchGroup.leave()
}
dispatchGroup.notify(queue: .main) {
completion(groupResult)
}

当每个任务完成时,您希望表达这样的想法:

如果上一个小组结果为真,则组结果应为真,并且成功为真

相关内容

  • 没有找到相关文章

最新更新