Reactor

1,316 阅读4分钟

Reactor 中,MonoFlux 提供了丰富的 API 来处理响应式流,其中 defer 是一个重要的操作符。除了 defer 之外,还有许多其他常用的操作符,可以帮助你灵活地控制异步数据流的产生、转换和处理。以下是 defer 以及一些其他常用 API 的详细介绍。

1. Mono.defer()Flux.defer()

简介:

defer() 允许你推迟 MonoFlux 的创建,直到有订阅者订阅时才执行创建逻辑。它通常用于动态地生成新的 MonoFlux 实例,而不是在代码执行时立即创建。

使用场景:

  • 当你需要在每次订阅时都重新计算或生成新的流时,defer() 非常有用。
  • 避免在类加载时立即执行某些逻辑,而是在需要时(即有订阅者订阅时)才执行。

示例:

Mono<String> deferredMono = Mono.defer(() -> {
    System.out.println("Creating Mono");
    return Mono.just("Hello, World!");
});

System.out.println("Before subscription");
deferredMono.subscribe(System.out::println);  // 订阅时才会创建 Mono
System.out.println("After subscription");

输出:

Before subscription
Creating Mono
Hello, World!
After subscription

从输出可以看出,defer() 的创建逻辑直到有订阅者时才执行,而不是在声明时立即执行。

若没有 defer()Mono.just() 会在声明时立即执行创建逻辑。

2. Mono.fromCallable()

简介:

fromCallable() 可以从 Callable 创建一个 Mono,它会在订阅时执行 Callable,并将返回的结果作为 Mono 的元素。如果 Callable 抛出异常,Mono 会发出一个错误信号。

示例:

Mono<String> mono = Mono.fromCallable(() -> {
    Thread.sleep(1000); // 模拟长时间的计算
    return "Result";
});

mono.subscribe(
    result -> System.out.println("Received: " + result),
    error -> System.err.println("Error: " + error)
);

这个 Mono 将在订阅时执行 Callable,如果 Callable 抛出异常,则 Mono 会发出错误信号。

3. Mono.just()

简介:

just() 是最简单的创建 Mono 的方法之一,表示一个包含静态固定值的 Mono。它会立即创建一个包含指定值的 Mono,并在订阅时发出该值。

示例:

Mono<String> mono = Mono.just("Hello");

mono.subscribe(System.out::println);

输出:

Hello

注意:Mono.just() 在声明时就会创建 Mono,而不像 defer() 那样推迟创建。

4. Mono.fromRunnable()

简介:

fromRunnable() 可以从一个 Runnable 创建 Mono,它会在订阅时执行 Runnable,但不会发出任何元素,只会发出完成信号。

示例:

Mono<Void> mono = Mono.fromRunnable(() -> {
    System.out.println("Running a task...");
});

mono.subscribe(
    System.out::println,
    System.err::println,
    () -> System.out.println("Task completed")
);

输出:

Running a task...
Task completed

fromRunnable() 适用于需要在订阅时执行一个任务,但不需要返回值的场景。

5. Mono.delay()Flux.interval()

简介:

  • Mono.delay():创建一个 Mono,该 Mono 会延迟一段时间后发出元素。
  • Flux.interval():创建一个 Flux,该 Flux 会以固定的时间间隔发出元素。

示例:Mono.delay()

Mono<Long> delayedMono = Mono.delay(Duration.ofSeconds(2));

delayedMono.subscribe(System.out::println);

这个 Mono 会在两秒后发出一个 Long 值(通常是从 0 开始计数)。

示例:Flux.interval()

Flux<Long> intervalFlux = Flux.interval(Duration.ofSeconds(1));

intervalFlux.take(5).subscribe(System.out::println); // 只获取前5个元素

Flux.interval() 每秒发出一个递增的 Long 值。take(5) 表示只获取前 5 个值。

6. Mono.create()Flux.create()

简介:

create() 是手动创建 MonoFlux 的一种方法,它允许你通过编程的方式来控制数据的发射。

示例:Mono.create()

Mono<String> mono = Mono.create(sink -> {
    sink.success("Hello from create");
});

mono.subscribe(System.out::println);

你可以通过 sink 来手动发射一个成功信号或错误信号。

示例:Flux.create()

Flux<String> flux = Flux.create(sink -> {
    sink.next("A");
    sink.next("B");
    sink.next("C");
    sink.complete();
});

flux.subscribe(System.out::println);

Flux.create() 允许你手动控制流的元素发射和完成信号。

7. Mono.error()Mono.empty()

简介:

  • Mono.error():创建一个立即发出错误信号的 Mono
  • Mono.empty():创建一个不发出任何数据但立即完成的 Mono

示例:Mono.error()

Mono<String> mono = Mono.error(new RuntimeException("Something went wrong"));

mono.subscribe(
    System.out::println,
    error -> System.err.println("Error: " + error.getMessage())
);

输出:

Error: Something went wrong

示例:Mono.empty()

Mono<String> mono = Mono.empty();

mono.subscribe(
    System.out::println,
    System.err::println,
    () -> System.out.println("Completed")
);

输出:

Completed

Mono.empty() 用于表示没有数据但成功完成的 Mono

8. Mono.when()Flux.merge()

简介:

  • Mono.when():等待多个 Mono 完成,并返回一个新的 Mono<Void>
  • Flux.merge():合并多个 Flux,并同时发出它们的元素。

示例:Mono.when()

Mono<Void> combined = Mono.when(
    Mono.delay(Duration.ofSeconds(1)),
    Mono.delay(Duration.ofSeconds(2))
);

combined.subscribe(
    System.out::println,
    System.err::println,
    () -> System.out.println("All tasks completed")
);

Mono.when() 会等待所有 Mono 完成后,才发出完成信号。

示例:Flux.merge()

Flux<String> flux1 = Flux.just("A", "B", "C");
Flux<String> flux2 = Flux.just("D", "E", "F");

Flux<String> mergedFlux = Flux.merge(flux1, flux2);

mergedFlux.subscribe(System.out::println);

Flux.merge() 会将多个 Flux 合并成一个 Flux,并同时发出它们的元素。

9. Mono.zip()Flux.zip()

简介:

zip() 用于将多个 MonoFlux 的元素组合成一个新的 MonoFlux,并将结果作为一个对象发出。

示例:Mono.zip()

Mono<String> mono1 = Mono.just("Hello");
Mono<String> mono2 = Mono.just("World");

Mono<String> zipped = Mono.zip(mono1, mono2, (a, b) -> a + " " + b);

zipped.subscribe(System.out::println);

输出:

Hello World

示例:Flux.zip()

Flux<String> flux1 = Flux.just("A", "B", "C");
Flux<String> flux2 = Flux.just("1", "2", "3");

Flux<String> zippedFlux = Flux.zip(flux1, flux2, (a, b) -> a + b);

zippedFlux.subscribe(System.out::println);

输出:

A1
B2
C3

zip()MonoFlux 中的使用场景是,将来自多个流的数据一一对应地进行组合。

总结

Reactor 提供了丰富的 API 来处理响应式数据流,从基本的 just()from() 到高级的 defer()zip()merge(),这些操作符为处理异步和非阻塞的数据流提供了极大的灵活性。通过这些工具,开发者可以轻松构建高效的异步应用程序,同时保持代码的简洁和可读性。