Search code examples
spring-webfluxproject-reactor

What is the difference between block() , subscribe() and subscribe(-)


Mono.delay(Duration.ofMillis(10)).map(d -> {
            System.out.println(d);
            return d;
        }).block();

output : 0

Not able to see any output on console when I am calling with subscribe() or subscribe(-) methods instead of block()

Mono.delay(Duration.ofMillis(10)).map(d -> {
        System.out.println(d);
        return d;
    }).subscribe(System.out::println);

Do we need to use only doOnSubscribe(-) after this Mono.delay(-) method?

 Mono.delay(Duration.ofMillis(10)).doOnSubscribe(s -> {
        System.out.println("its printing doOnSubscribe");
    }).map(d -> {
        System.out.println(d);
        return d;
    }).subscribe(System.out::println);

output it's printing doOnSubscribe


Solution

  • Your block() call explicitly holds the main thread until the publisher completes. By the time it's completed, it's executed the map() call, therefore printing the value.

    Your subscribe() call on the other hand asynchronously executes the Mono on a separate scheduler, leaving your main thread to complete. Since the scheduler used by default uses daemon threads to execute your subscription, your program won't wait for it to complete before terminating.

    If you introduce a delay long enough for the Mono to complete, you'll see the result you expect:

    Mono.delay(Duration.ofMillis(10)).map(d -> {
        System.out.println(d);
        return d;
    }).subscribe(System.out::println);
    
    Thread.currentThread().sleep(500);
    

    0 is then printed twice, once for the map() call and once by the System.out::println being used as a consumer.

    In a real world use case you obviously won't just put in arbitrary sleep() calls - a CountDownLatch would be a more sensible choice:

    CountDownLatch cdl = new CountDownLatch(1);
    Mono.delay(Duration.ofMillis(10))
            .map(d -> {
                System.out.println(d);
                return d;
            })
            .doOnTerminate(() -> cdl.countDown())
            .subscribe(System.out::println);
    cdl.await();