反应堆中的地图vs平面地图 [英] map vs flatMap in reactor
问题描述
关于 RxJava ,但我想了解它在Reactor中的工作原理.
I've found a lot of answers regarding RxJava, but I want to understand how it works in Reactor.
我目前的理解非常模糊,我倾向于认为map是同步的,而flatMap是异步的,但是我真的无法解决它.
My current understanding is very vague, i tend to think of map as being synchronous and flatMap to be asynchronous but I can't really get my had around it.
这里是一个例子:
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
.
I have files (a Flux<FilePart>
) and i want to copy it to some UPLOAD_ROOT
on the server.
此示例摘自一本书.
我可以将所有 .map
更改为 .flatMap
,反之亦然,一切仍然正常.我不知道有什么区别.
I can change all the .map
to .flatMap
and vice versa and everything still works. I wonder what the difference is.
推荐答案
-
map
用于同步,非阻塞,一对一转换 -
flatMap
用于异步(非阻塞)从1到N的转换 map
is for synchronous, non-blocking, 1-to-1 transformationsflatMap
is for asynchronous (non-blocking) 1-to-N transformations-
map
接受Function< T,U>
,并返回Flux< U>
-
flatMap
接受Function< T,Publisher< V>>
,并返回Flux< V>
map
takes aFunction<T, U>
and returns aFlux<U>
flatMap
takes aFunction<T, Publisher<V>>
and returns aFlux<V>
区别在方法签名中可见:
The difference is visible in the method signature:
这是主要提示:您可以将 Function< T,Publisher< V>>
传递给 map
,但不会不知道如何处理 Publishers
,这将导致 Flux< Publisher< V>>
(一系列惰性发布者).
That's the major hint: you can pass a Function<T, Publisher<V>>
to a map
, but it wouldn't know what to do with the Publishers
, and that would result in a Flux<Publisher<V>>
, a sequence of inert publishers.
另一方面, flatMap
期望每个 T
的 Publisher< V>
.它知道如何处理它:订阅它并在输出序列中传播它的元素.结果,返回类型为 Flux< V>
: flatMap
将把每个内部 Publisher< V>
展平为全部 V
.
On the other hand, flatMap
expects a Publisher<V>
for each T
. It knows what to do with it: subscribe to it and propagate its elements in the output sequence. As a result, the return type is Flux<V>
: flatMap
will flatten each inner Publisher<V>
into the output sequence of all the V
s.
关于1-N方面:
, flatMap
将其映射到 Publisher< V>
.在某些情况下(例如HTTP请求),该发布者将仅发出一项,在这种情况下,我们非常接近异步 map
.
for each <T>
input element, flatMap
maps it to a Publisher<V>
. In some cases (eg. an HTTP request), that publisher will emit only one item, in which case we're pretty close to an async map
.
但这就是简朴的情况.一般情况是, Publisher
可以发出多个元素,而 flatMap
也可以正常工作.
But that's the degenerate case. The generic case is that a Publisher
can emit multiple elements, and flatMap
works just as well.
以一个示例为例,假设您有一个反应性数据库,并且您从一系列用户ID中获得了flatMap,并且请求返回了用户的 Badge
集.最后,所有这些用户的所有徽章都只有一个 Flux< Badge>
.
For an example, imagine you have a reactive database and you flatMap from a sequence of user IDs, with a request that returns a user's set of Badge
. You end up with a single Flux<Badge>
of all the badges of all these users.
地图
是否真正同步并且无阻塞?
Is map
really synchronous and non-blocking?
是:它在操作员应用该方法(一个简单的方法调用,然后该操作员发出结果)的方式中是同步的,并且在函数本身不应该阻止该操作员调用它的意义上说是非阻塞的.换句话说,它不应该引入延迟.这是因为 Flux
总体上还是异步的.如果它阻止中间序列,将影响其余的 Flux
处理,甚至其他 Flux
.
Yes: it is synchronous in the way the operator applies it (a simple method call, and then the operator emits the result) and non-blocking in the sense that the function itself shouldn't block the operator calling it. In other terms it shouldn't introduce latency. That's because a Flux
is still asynchronous as a whole. If it blocks mid-sequence, it will impact the rest of the Flux
processing, or even other Flux
.
如果您的地图功能正在阻止/引入了延迟,但无法转换为返回 Publisher
,请考虑使用 publishOn
/ subscribeOn
来抵消该阻止在单独的线程上工作.
If your map function is blocking/introduces latency but cannot be converted to return a Publisher
, consider publishOn
/subscribeOn
to offset that blocking work on a separate thread.
这篇关于反应堆中的地图vs平面地图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!