how to avoid .flatMap(x-> reactiveAction(x).thenReturn(x))

Viewed 658

During some reactive programming in Java using project reactor library, I stumbled upon a pattern for which I'm wondering if there is out of box support?

So I want the code below:

Mono.just("hello")
    .flatMap(hello -> reactiveAction(hello).thenReturn(hello))
    ..
    .;

to be turned into something like:

Mono.just("hello")
    .coolOperation(this::reactiveAction)
    ..
    .;   

I can not use doOnNext because what I want to do inside reactiveAction is not side effect. and reactive action is:

Mono<Integer> reactiveAction(String text){
  return ....
}
3 Answers

Have you considered Mono#delayUntil?

Mono.just("hello")
    .delayUntil(hello -> reactiveAction(hello))
    ..
    .;

I can't find built-in solution, but you could create utility function:

public static <T> Function<Mono<T>, Publisher<T>> coolOperation(
        Function<T, Mono<?>> companionMonoFunction) {
    return originalMono -> originalMono
            .flatMap(t -> companionMonoFunction.apply(t)
                    .thenReturn(t));
}

And now you can use it with transform or transformDeffered:

Mono.just("hello")
    .transform(coolOperation(this::reactiveAction))
    ...;

But for me it doesn't look much prettier :)

EDIT: see @bsideup answer, looks like delayUntil could fit the bill.

My original answer as an alternative suggestion:

I don't think there is any baked-in syntactic sugar to do this, as the "perform an async operation that depends on the original onNext" is the very definition of flatMap. We actually added the thenReturn(foo) as syntactic sugar over .then(Mono.just(foo)).

If you want to further shorten the code, offer an alternative to reactiveAction that also returns the original value:

Mono<String> reactiveActionBackground(String text){
  return reactiveAction(text).thenReturn(text);
}

which can then be invoked directly on flatMap rather than through transform:

Mono.just("hello")
    .flatMap(this::reactiveActionBackground);
Related