问题描述
-
map
用于同步,非阻塞,一对一转换 -
flatMap
用于异步(非阻塞)1-to-N转换
区别在方法签名中可见:
-
map
取aFunction<T, U>
并返回aFlux<U>
-
flatMap
取aFunction<T, Publisher<V>>
并返回aFlux<V>
这是主要提示:您 可以 将传递Function<T,
Publisher<V>>
给map
,但它不知道如何处理Publishers
,这将导致Flux<Publisher<V>>
一系列惰性发布者。
另一方面,每个flatMap
期望a 。它知道如何处理它:订阅它并在输出序列中传播它的元素。其结果,返回类型:将压扁每个内进入的输出序列 的所有
的第Publisher<V>``T``Flux<V>``flatMap``Publisher<V>
__V
对于每个<T>
输入元素,flatMap
将其映射到Publisher<V>
。在某些情况下(例如HTTP请求),该发布者将仅发出一项,在这种情况下,我们非常接近asyncmap
。
但这就是简朴的情况。一般情况是a Publisher
可以发出多个元素,并且flatMap
效果也一样。
举例来说,假设您有一个反应型数据库,并且您从一系列用户ID中获取了flatMap,并且请求返回了用户的Badge
。您最终Flux<Badge>
将获得所有这些用户的所有徽章。
是的:它在操作员应用它的方式(一个简单的方法调用,然后操作员发出结果)上是同步的,并且在函数本身不应该阻止操作员调用它的意义上说是非阻塞的。换句话说,它不应该引入延迟。这是因为Flux
a总体上还是异步的。如果阻塞中间序列,则将影响其余的Flux
处理过程,甚至其他过程Flux
。
如果您的地图函数正在阻止/引入延迟,但无法将其转换为返回Publisher
,请考虑publishOn
/subscribeOn
以抵消在单独线程上的阻止工作。
解决方法
我目前的理解非常模糊,我倾向于认为map是同步的,而flatMap是异步的,但是我真的无法解决它。
这是一个例子:
files.flatMap { it ->
Mono.just(Paths.get(UPLOAD_ROOT,it.filename()).toFile())
.map {destFile ->
destFile.createNewFile()
destFile
}
.flatMap(it::transferTo)
}.then()
我有文件(a Flux<FilePart>
),我想将其复制到UPLOAD_ROOT
服务器上的某些文件中。
本示例摘自一本书。
我可以将所有更改为.map
to .flatMap
,反之亦然,一切仍然正常。我不知道有什么区别。