はじめに
Combineを利用していて、RxSwiftでできていたことをどうすればできるか迷ったため調べた際のメモ
やりたいこと
通信処理Aして、その値を元に非同期処理Bを実行したい。
例)ユーザー情報取得し、その情報をローカルの保存領域に保存する。等
環境
Xcode 11.6
Playground
結果
RxSwiftと似た形でflatMapを利用すればできる。
同期的に実行するには maxPublishers: .max(1)
を指定する。
Playground
var cancellables = Set<AnyCancellable>()
// 非同期処理A
func asyncAAA() -> Future<String, Error> {
Future<String, Error> { promise in
// 非同期の処理
DispatchQueue.main.async {
print("\(#function)")
promise(.success("AAA"))
}
}
}
// 非同期処理B
func asyncBBB(string: String) -> Future<String, Error> {
Future<String, Error> { promise in
// 非同期の処理
DispatchQueue.main.async {
print("\(#function) value:\(string)")
promise(.success(string + "BBB"))
}
}
}
// 実行部
asyncAAA()
.flatMap(maxPublishers: .max(1)) { (value) -> Future<String, Error> in
asyncBBB(string: value)
}
.sink(receiveCompletion: { (completion) in
print("sink(receiveCompletion: \(completion))")
}) { (value) in
print("sink(value: \(value))")
}.store(in: &cancellables)
console
asyncAAA() // 非同期処理Aを実行
asyncBBB(string:) value:AAA // 非同期処理Aの結果をもとに非同期処理Bが実行
sink(value: AAABBB) // 非同期処理Bの実行結果をsink先で受け取り
sink(receiveCompletion: finished) // Streamの終了
思考フロー
RxSwiftのflatMapはCombineでどう表現するか?
公式ドキュメント でflatMapの役割を確認。
上流のPublisherを変換する役割を担っているため、同じようなことができそう。
Transforms all elements from an upstream publisher into a new publisher up to a maximum number of publishers you specify.
maxPublishers
は何か?
maxPublishers
は同時実行回数を指定します。
処理中に割り込みで新規イベントを受け付けないようにするため .max(1)
を指定しています。
詳細な動作は @yimajo さんの CombineのflatMapで実行数を制御する にとてもわかり易くまとまっていました。