我已经找到了很多关于RxJava的答案,但我想了解它在Reactor中是如何工作的.
我目前的理解非常模糊,我倾向于认为map是同步的,而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,反之亦然,一切仍然有效.我想知道区别是什么.
> flatMap用于异步(非阻塞)1对N转换
差异在方法签名中可见:
> map采用函数< T,U>并返回Flux< U>
> flatMap采用函数< T,Publisher< V>>并返回Flux< V>
这是主要提示:您可以传递函数< T,Publisher< V>>到地图,但它不知道如何处理发布者,这将导致Flux< Publisher< V>>,一系列惰性发布者.
另一方面,flatMap期望发布者< V>对于每个T.它知道如何处理它:订阅它并在输出序列中传播它的元素.结果,返回类型是Flux< V>:flatMap将展平每个内部发布者< V>.进入所有V的输出序列.
关于1-N方面:
对于每个< T> input元素,flatMap将其映射到Publisher< V>.在某些情况下(例如,HTTP请求),该发布者将只发出一个项目,在这种情况下,我们非常接近异步映射.
但那是堕落的情况.一般情况是Publisher可以发出多个元素,flatMap也可以.
例如,假设您有一个反应数据库,并且您从一系列用户ID中获得flatMap,并返回用户的徽章集.您最终得到一个Flux<徽章>所有这些用户的所有徽章.
地图是否真的同步且无阻塞?
是的:它在操作符应用它的方式上是同步的(一个简单的方法调用,然后运算符发出结果)和非阻塞,因为函数本身不应该阻止操作符调用它.换句话说,它不应该引入延迟.这是因为Flux整体上仍然是异步的.如果它阻止中间序列,它将影响其余的Flux处理,甚至其他Flux.
如果您的map函数阻塞/引入延迟但无法转换为返回Publisher,请考虑使用publishOn / subscribeOn来抵消单独线程上的阻塞工作.