41

I don't understand the use and the difference between then, thenEmpty, thenMany and flatMapMany on Flux or Mono in spring webflux.

Chirlo
  • 5,989
  • 1
  • 29
  • 45
Amr Khaled
  • 421
  • 1
  • 4
  • 5
  • 3
    I found the answer in project reactor documentation https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html – Amr Khaled Jan 15 '18 at 12:51
  • Funny how this "question" got 30 upvotes, without actually being a question :) 1+ – Eugene Aug 13 '22 at 19:52

1 Answers1

75
  • flatMap vs flatMapMany

In functional programming, flatMap returns the same type than the type that bear the method, so for Mono<T>, flatMap returns a Mono. Which means that only one element can be emitted by the inner Publisher (or that it is truncated). We enforced that by having Mono#flatMap take a Function<T, Mono<R>>.

As a consequence, we needed an alternative for more arbitrary Publisher that could emit more than one element. Hence Mono#flatMapMany(Function<T, Publisher<R>>) which returns a Flux<R>.

TL;DR: Mono#flatMap is for asynchronous but 1-to-1 transformation of the element in the source Mono, Mono#flatMapMany is for 1-to-N asynchronous transformation (like Flux#flatMap).

  • then, thenEmpty and thenMany

All the thenXXX methods on Mono have one semantic in common: they ignore the source onNext signals and react on completion signals (onComplete and onError), continuing the sequence at this point with various options. As a consequence, this can change the generic type of the returned Mono:

  1. then will just replay the source terminal signal, resulting in a Mono<Void> to indicate that this never signals any onNext.
  2. thenEmpty not only returns a Mono<Void>, but it takes a Mono<Void> as a parameter. It represents a concatenation of the source completion signal then the second, empty Mono completion signal. In other words, it completes when A then B have both completed sequentially, and doesn't emit data.
  3. thenMany waits for the source to complete then plays all the signals from its Publisher<R> parameter, resulting in a Flux<R> that will "pause" until the source completes, then emit the many elements from the provided publisher before replaying its completion signal as well.
Simon Baslé
  • 27,105
  • 5
  • 69
  • 70
  • I'm using `thenMany` to continue after a guard. Is it a good pattern? I.e. the guard returns `Mono.error(...)` if precondition failed, `Mono.empty()` otherwise. Then I have `thenMany` to continue the computation and return `Flux` in my webflux app. – wilmol Sep 24 '20 at 11:54
  • yes that should work @wilmol, although I imagine the `Mono.error` is used inside a `flatMap` (that you called a "guard")? in which case it would be less overhead to directly return the `Flux` in the else branch of the flatmap rather than from the thenMany – Simon Baslé Sep 25 '20 at 17:11
  • Note that all of the ``then`` Mono's will be subscribed althougth any of then throw an error, while ``map``'s won't – Gonzalo Nov 05 '21 at 14:53
  • https://intojava.wordpress.com/2020/11/25/difference-between-flatmap-and-flatmapmany-in-webflux/ – Hariom Yadav Nov 09 '21 at 08:32