Flux
下图显示了如何Flux转换项目:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1Owuiu6V-1686710988310)(null)]
通量
A Flux是一个标准Publisher,表示 0 到 N 个发射项目的异步序列,可选地由完成信号或错误终止。正如在 Reactive Streams 规范中一样,这三种类型的信号转换为对下游订阅者的onNext、onComplete和onError方法的调用。
具有这种大范围的可能信号,Flux是通用的反应式类型。请注意,所有事件,即使是终止事件,都是可选的:没有onNext事件,只有一个 onComplete事件表示一个空的有限序列,但删除onComplete并且您有一个无限的空序列(不是特别有用,除了围绕取消的测试)。同样,无限序列不一定是空的。例如,Flux.interval(Duration) 产生一个Flux无限的并从时钟发出定期滴答声。
Mono
下图显示了如何Mono转换项目:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gp8ort6l-1686710988994)(null)]
单核细胞增多症
A Mono是一个专门的,它通过Publisher信号最多发出一个项目, 然后以一个信号终止(成功,有或没有值),或者只发出一个信号(失败)。onNextonCompleteMonoonErrorMono
大多数实现都应该在调用后Mono立即调用onComplete它们 。是一个异常值:它不发出任何信号,这在技术上并没有被禁止,尽管在测试之外并不是非常有用。另一方面,明确禁止and的组合。SubscriberonNextMono.never()onNextonError
Mono仅提供可用于 a 的运算符的子集Flux,并且一些运算符(特别是那些将 theMono与另一个结合的运算符Publisher)切换到 a Flux。例如,Mono#concatWith(Publisher)返回一个FluxwhileMono#then(Mono) 返回另一个Mono。
请注意,您可以使用 a Mono来表示只有完成概念的无值异步进程(类似于 a Runnable)。要创建一个,您可以使用一个空的 Mono.
简单的方法创建Flux和Mono并且订阅他们
lux<String> seq1 = Flux.just("foo", "bar", "foobar");
List<String> iterable = Arrays.asList("foo", "bar", "foobar");
Flux<String> seq2 = Flux.fromIterable(iterable);
Mono<String> noData = Mono.empty();
Mono<String> data = Mono.just("foo");
Flux<Integer> numbersFromFiveToSeven = Flux.range(5, 3);
subscribe() 方法
subscribe();
subscribe(Consumer<? super T> consumer);
subscribe(Consumer<? super T> consumer,
Consumer<? super Throwable> errorConsumer);
subscribe(Consumer<? super T> consumer,
Consumer<? super Throwable> errorConsumer,
Runnable completeConsumer);
subscribe(Consumer<? super T> consumer,
Consumer<? super Throwable> errorConsumer,
Runnable completeConsumer,
Consumer<? super Subscription> subscriptionConsumer);
1. 订阅并触发序列。
2. 对每个产生的元素做处理。
3. 处理每个元素值,但也要对错误做出反应。
4. 处理元素值和错误,但还要在序列成功完成时运行一些代码。
5. 处理元素值和错误并成功完成,但也要处理 此subscribe调用时Subscription产生的内容。
订阅并触发
Flux<Integer> ints = Flux.range(1, 3);
ints.subscribe(i -> System.out.println(i));
output:
1
2
3
订阅并处理错误
Flux<Integer> ints = Flux.range(1, 4)
.map(i -> {
if (i <= 3) return i;
throw new RuntimeException("Got to 4");
});
ints.subscribe(i -> System.out.println(i),
error -> System.err.println("Error: " + error));
output:
1
2
3
Error: java.lang.RuntimeException: Got to 4
订阅并在处理完成后执行代码
Flux<Integer> ints = Flux.range(1, 3);
ints.subscribe(i -> System.out.println(i),
error -> System.err.println("Error " + error),
() -> System.out.println("Done"));
output:
1
2
3
完成
订阅并捕获错误,处理,完成后任务,并处理订阅详情
Flux<Integer> ints = Flux.range(1, 4);
ints.subscribe(i -> System.out.println(i),
error -> System.err.println("Error " + error),
() -> System.out.println("Done"),
sub -> sub.request(10));
使用Disposable取消subscribe()
所有这些基于 lambda 的变体subscribe()都有一个Disposable返回类型。在这种情况下,接口表示可以通过调用其dispose()方法取消Disposable订阅的事实。
对于Fluxor Mono,取消是源应该停止产生元素的信号。但是,不能保证立即生效:某些来源可能会生成元素的速度非常快,以至于它们甚至可以在收到取消指令之前完成。
Disposable课程中提供了一些实用程序Disposables。其中,
1. Disposables.swap()创建一个Disposable包装器,让您可以原子地取消和替换具体的Disposable. 这可能很有用,例如,在您想要取消请求并在用户单击按钮时将其替换为新请求的 UI 场景中。处理包装器本身会关闭它。这样做会处理当前的具体值和所有未来尝试的替换。
2. Disposables.composite(…). 这种组合让您可以收集多个Disposable (例如,与服务调用相关联的多个进行中的请求)并在稍后一次性处理所有这些请求。一旦dispose()调用了组合的方法,任何添加另一个的尝试都会Disposable立即释放它。
subcribie()的替代方案,编写Subcrbier类
还有一种比使用subscribe更通用的方法,它采用更成熟的方法,Subscriber而不是从 lambda 中组合一个。为了帮助编写这样的Subscriber代码,我们提供了一个名为 的可扩展类BaseSubscriber。
的实例BaseSubscriber(或其子类)是单次使用的,这意味着如果订阅了第二个,则BaseSubscriber取消对第一个的订阅。这是因为两次使用实例会违反反应流规则,即不得并行调用a 的方法。因此,匿名实现只有在对. PublisherPublisheronNextSubscriberPublisher#subscribe(Subscriber)
现在我们可以实现其中之一。我们称之为SampleSubscriber. 以下示例显示了如何将其附加到 a Flux:
SampleSubscriber<Integer> ss = new SampleSubscriber<Integer>();
Flux<Integer> ints = Flux.range(1, 4);
ints.subscribe(ss);
SampleSubscriber.java
package io.projectreactor.samples;
import org.reactivestreams.Subscription;
import reactor.core.publisher.BaseSubscriber;
public class SampleSubscriber<T> extends BaseSubscriber<T> {
public void hookOnSubscribe(Subscription subscription) {
System.out.println("Subscribed");
request(1);
}
public void hookOnNext(T value) {
System.out.println(value);
request(1);
}
}
BaseSubscriber还提供了requestUnbounded()一种切换到无界模式(相当于request(Long.MAX_VALUE))的方法,以及一种cancel()方法。
它还有额外的钩子:hookOnComplete, hookOnError, hookOnCancel, and hookFinally (总是在序列终止时调用,终止类型作为SignalType参数传入)
您几乎肯定想要实现hookOnError、hookOnCancel和 hookOnComplete方法。您可能还想实现该hookFinally方法。 是执行有界请求的绝对最小实现。 Subscriber