RxJava に関する多くの答えを見つけましたが、Reactorでの動作を理解したいと思います。
私の現在の理解は非常に曖昧です。地図は同期的であり、flatMapは非同期であると考える傾向がありますが、実際に理解することはできません。
以下に例を示します。
files.flatMap { it ->
Mono.just(Paths.get(UPLOAD_ROOT, it.filename()).toFile())
.map {destFile ->
destFile.createNewFile()
destFile
}
.flatMap(it::transferTo)
}.then()
ファイル(Flux<FilePart>
)があり、サーバー上のいくつかのUPLOAD_ROOT
にコピーしたい。
この例は本から取られています。
すべての.map
を.flatMap
に、またはその逆に変更できますが、すべてが引き続き機能します。違いは何でしょうか。
map
は、同期、非ブロッキング、1対1変換用ですflatMap
は、非同期(非ブロッキング)1-N変換用です違いはメソッドシグネチャで確認できます。
map
はFunction<T, U>
を取り、Flux<U>
を返しますflatMap
はFunction<T, Publisher<V>>
を取り、Flux<V>
を返しますそれが主要なヒントです。あなたはcanFunction<T, Publisher<V>>
をmap
に渡しますが、Publishers
をどうするかわかりません。 Flux<Publisher<V>>
で、不活性なパブリッシャーのシーケンス。
一方、flatMap
では、T
ごとにPublisher<V>
が必要です。それをどうするかを知っています。サブスクライブし、その要素を出力シーケンスに伝播します。その結果、戻り値の型はFlux<V>
です。flatMap
は、各内部Publisher<V>
をall the V
sの出力シーケンスにフラット化します。
1-Nアスペクトについて:
<T>
入力要素ごとに、flatMap
はそれをPublisher<V>
にマップします。場合によっては(たとえば、HTTP要求)、そのパブリッシャーは1つのアイテムのみを発行します。その場合、非同期map
にかなり近づいています。
しかし、それは退化したケースです。一般的なケースは、Publisher
が複数の要素を放出でき、flatMap
も同様に機能するということです。
例として、リアクティブデータベースがあり、ユーザーの一連のBadge
を返すリクエストを使用して、ユーザーIDのシーケンスからflatMapを想像してください。これらすべてのユーザーのすべてのバッジのうち、単一のFlux<Badge>
になります。
map
は本当に同期であり、ノンブロッキング?
はい:オペレーターが適用する方法で同期し(単純なメソッド呼び出し、そしてオペレーターが結果を出力する)、関数自体がそれを呼び出すオペレーターをブロックしてはならないという意味で非ブロッキングです。言い換えれば、レイテンシを導入するべきではありません。 Flux
は全体としてまだ非同期であるためです。シーケンスの途中でブロックすると、残りのFlux
処理、または他のFlux
にも影響します。
マップ関数がブロッキング/レイテンシーを導入しているが、Publisher
を返すように変換できない場合は、publishOn
/subscribeOn
を考慮して、別のスレッドでのブロッキング作業を相殺してください。