我找到了很多关于 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
反之亦然,一切仍然有效。我想知道有什么区别。
最佳答案
-
map
用于同步、非阻塞、一对一的转换 -
flatMap
用于异步(非阻塞)1 到 N 转换
差异在方法签名中可见:
-
map
需要Function<T, U>
并返回Flux<U>
-
flatMap
需要Function<T, Publisher<V>>
并返回Flux<V>
这是主要提示:您可以传递 Function<T, Publisher<V>>
到 map
, 但它不知道如何处理 Publishers
,这将导致 Flux<Publisher<V>>
,一系列惰性发布者。
另一方面,flatMap
期望一个 Publisher<V>
对于每个 T
.它知道如何处理它:订阅它并在输出序列中传播它的元素。结果,返回类型为 Flux<V>
: flatMap
将压平每个内部 Publisher<V>
进入所有 V
的输出序列
关于1-N方面:
对于每个 <T>
输入元素,flatMap
将其映射到 Publisher<V>
.在某些情况下(例如 HTTP 请求),该发布者将只发出一个项目,在这种情况下我们非常接近异步 map
.
但这是退化的情况。一般情况是 Publisher
可以发出多个元素,并且 flatMap
效果也一样。
举个例子,假设你有一个响应式(Reactive)数据库,你从一系列用户 ID 中进行 flatMap,请求返回用户的 Badge
集。 .你最终得到一个 Flux<Badge>
所有这些用户的所有徽章。
是map
真的是同步和非阻塞吗?
是的:它在运算符应用它的方式上是同步的(一个简单的方法调用,然后运算符发出结果)并且在函数本身不应该阻塞调用它的运算符的意义上是非阻塞的。换句话说,它不应该引入延迟。那是因为 Flux
整体还是异步的。如果它阻塞中间序列,它将影响 Flux
的其余部分加工,甚至其他Flux
.
如果您的 map 功能阻塞/引入延迟但无法转换为返回 Publisher
, 考虑 publishOn
/subscribeOn
抵消单独线程上的阻塞工作。
关于java - react 堆中的 map 与平面 map ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49115135/