I have a protocol defined as follows:
protocol Prompter {
func promptIfNeeded() async -> Bool
}
And an array of Prompter
conforming types:
var prompters: [Prompter] { [PrompterA(), PrompterB()] }
Currently, I iterate through this array, prompting each message to the user, one by one, using async
await
:
for prompter in prompters {
let result = await prompter.promptIfNeeded()
print("The result is \(result)")
}
However, I’m curious about leveraging Combine
publishers instead of async
await
. Any guidance on this?
Note - each prompt must wait for the previous one to finish
If you want them to execute sequentially, you can use a Publishers.Sequence
with a flatMap
with a Subscribers.Demand
of .max(1)
. Obviously, the method would need to return a Future
. So, perhaps:
protocol Prompter {
func promptIfNeeded() -> Future<Bool, Never>
}
struct PrompterA: Prompter {
func promptIfNeeded() -> Future<Bool, Never> {
Future { promise in
…
promise(.success(result)) // where `result` is some `Bool`
}
}
}
struct PrompterB: Prompter { … }
class Foo {
var cancellables: Set<AnyCancellable> = []
func performPrompts() {
let prompters: [Prompter] = [PrompterA(), PrompterB()]
Publishers.Sequence(sequence: prompters)
.flatMap(maxPublishers: .max(1)) { $0.promptIfNeeded() }
.sink { print($0) }
.store(in: &cancellables)
}
}
There are other variations on the theme, but hopefully this illustrates the idea: In Combine, one can use flatMap
with a maxPublishers
of .max(1))
for sequential behavior.