Reactor 中,Mono 和 Flux 提供了丰富的 API 来处理响应式流,其中 defer 是一个重要的操作符。除了 defer 之外,还有许多其他常用的操作符,可以帮助你灵活地控制异步数据流的产生、转换和处理。以下是 defer 以及一些其他常用 API 的详细介绍。
1. Mono.defer() 和 Flux.defer()
简介:
defer() 允许你推迟 Mono 或 Flux 的创建,直到有订阅者订阅时才执行创建逻辑。它通常用于动态地生成新的 Mono 或 Flux 实例,而不是在代码执行时立即创建。
使用场景:
- 当你需要在每次订阅时都重新计算或生成新的流时,
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() 是手动创建 Mono 或 Flux 的一种方法,它允许你通过编程的方式来控制数据的发射。
示例: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() 用于将多个 Mono 或 Flux 的元素组合成一个新的 Mono 或 Flux,并将结果作为一个对象发出。
示例: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() 在 Mono 或 Flux 中的使用场景是,将来自多个流的数据一一对应地进行组合。
总结
Reactor 提供了丰富的 API 来处理响应式数据流,从基本的 just()、from() 到高级的 defer()、zip() 和 merge(),这些操作符为处理异步和非阻塞的数据流提供了极大的灵活性。通过这些工具,开发者可以轻松构建高效的异步应用程序,同时保持代码的简洁和可读性。