javaspring-webfluxproject-reactor

what does Mono.defer() do?


I've come across Mono.defer() in some Spring webflux code

I looked up the method in the docs but don't understand the explanation:

"Create a Mono provider that will supply a target Mono to subscribe to for each Subscriber downstream"

please could I have an explanation and an example. Is there a place with a bunch of Reactor example code (their unit tests?) that I might reference.

thanks


Solution

  • It is a bit of an oversimplification but conceptually Reactor sources are either lazy or eager. More advanced ones, like an HTTP request, are expected to be lazily evaluated. On the other side the most simple ones like Mono.just or Flux.fromIterable are eager.

    By that, I mean that calling Mono.just(System.currentTimeMillis()) will immediately invoke the currentTimeMillis() method and capture the result. Said result is only emitted by the Mono once it is subscribed to. Subscribing multiple times doesn't change the value either:

    Mono<Long> clock = Mono.just(System.currentTimeMillis());
    //time == t0
    
    Thread.sleep(10_000);
    //time == t10
    clock.block(); //we use block for demonstration purposes, returns t0
    
    Thread.sleep(7_000);
    //time == t17
    clock.block(); //we re-subscribe to clock, still returns t0
    

    The defer operator is there to make this source lazy, re-evaluating the content of the lambda each time there is a new subscriber:

    Mono<Long> clock = Mono.defer(() -> Mono.just(System.currentTimeMillis()));
    //time == t0
    
    Thread.sleep(10_000);
    //time == t10
    clock.block(); //invoked currentTimeMillis() here and returns t10
    
    Thread.sleep(7_000);
    //time == t17
    clock.block(); //invoke currentTimeMillis() once again here and returns t17