如何在Combine中顺序迭代异步代码

问题描述 投票:0回答:1

我有一个协议定义如下:

protocol Prompter {
    func promptIfNeeded() async -> Bool
}

以及一组

Prompter
一致类型:

var prompters: [Prompter] { [PrompterA(), PrompterB()] }

目前,我迭代这个数组,使用

async
await
:

一条一条地向用户提示每条消息
for prompter in prompters {
    let result = await prompter.promptIfNeeded()
    print("The result is \(result)")
}

但是,我很好奇利用

Combine
出版商而不是
async
await
。有这方面的指导吗?

注意 - 每个提示必须等待前一个提示完成

swift async-await combine
1个回答
0
投票

如果您希望它们按顺序执行,您可以使用

Publishers.Sequence
flatMap
以及
Subscribers.Demand
.max(1)
。显然,该方法需要返回一个
Future
。所以,也许:

protocol Prompter {
    func prompt() -> Future<Bool, Never>
}

struct PrompterA: Prompter {
    func prompt() -> 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 prompts: [Prompter] = [PrompterA(), PrompterB()]

        Publishers.Sequence(sequence: prompts)
            .flatMap(maxPublishers: .max(1)) { $0.prompt() }
            .sink { print($0) }
            .store(in: &cancellables)
    }
}

主题还有其他变体,但希望这能说明这个想法。将

flatMap
maxPublishers
.max(1))
结合使用可能会实现您对合并的需求。

© www.soinside.com 2019 - 2024. All rights reserved.