我找到了很多关于RxJava https://stackoverflow.com/questions/22847105/when-do-you-use-map-vs-flatmap-in-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
to .flatMap
反之亦然,一切仍然有效。我想知道有什么区别。
-
map
用于同步、非阻塞、一对一转换
-
flatMap
用于异步(非阻塞)1 到 N 转换
差异在方法签名中可见:
-
map
需要一个Function<T, U>
并返回一个Flux<U>
-
flatMap
需要一个Function<T, Publisher<V>>
并返回一个Flux<V>
这是主要的提示:你can pass a Function<T, Publisher<V>>
to a map
,但它不知道如何处理Publishers
,这将导致Flux<Publisher<V>>
,一系列惰性发布者。
另一方面,flatMap
期望一个Publisher<V>
对于每个T
。它知道如何处理它:订阅它并在输出序列中传播它的元素。结果,返回类型为Flux<V>
: flatMap
将压平每个内部Publisher<V>
进入输出序列all the V
s.
关于1-N方面:
对于每个<T>
输入元素,flatMap
将其映射到Publisher<V>
。在某些情况下(例如 HTTP 请求),该发布者将仅发出一项,在这种情况下,我们非常接近异步map
.
但这就是堕落的情况。一般情况是Publisher
可以发出多个元素,并且flatMap
同样有效。
举个例子,假设您有一个反应式数据库,并且您从一系列用户 ID 中进行平面映射,并发出一个返回用户集合的请求Badge
。你最终会得到一个Flux<Badge>
所有这些用户的所有徽章。
Is map
真正同步并且非阻塞?
是的:它在运算符应用它的方式上是同步的(简单的方法调用,然后运算符发出结果),并且在函数本身不应该阻止调用它的运算符的意义上是非阻塞的。换句话说,它不应该引入延迟。那是因为一个Flux
整体还是异步的。如果它阻塞了中间序列,它将影响其余的序列Flux
处理,甚至其他Flux
.
如果您的地图函数阻塞/引入延迟但无法转换为返回Publisher
, 考虑publishOn
/subscribeOn
以抵消单独线程上的阻塞工作。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)