我正在使用弹簧通量向服务发送并行请求,这是它的非常简化的版本:
Flux.fromIterable(customers)
.flatMap { customer ->
client.call(customer)
} ...
我想知道如何取消这种磁通,例如,以某种方式获取对磁通的引用并告诉其关闭。
答案 0 :(得分:5)
您可能已经知道,对于反应性对象,all operators are lazy。这意味着流水线的执行被延迟到您订阅反应流之前。
因此,在您的示例中,没有任何要取消的操作,因为此时未发生任何事情。
但是假设您的示例扩展到:
Disposable disp = Flux.fromIterable(customers)
.flatMap { customer ->
client.call(customer)
}
.subscribe();
然后,如您所见,订阅将返回一个Disposable
对象,您可以根据需要取消整个操作,例如
disp.dispose()
dispose的文档说:
取消或处置基础任务或资源。
有another section of the documentation内容如下:
[运算符的]这些变体返回对订阅的引用 当没有更多数据时,可用于取消订阅 需要。取消后,来源应停止产生值,并且 清理它创建的所有资源。此取消和清理行为 在Reactor中由通用的
Disposable
接口表示。
因此取消流的执行在反应性对象方面并非没有复杂性,因为如果要在处理过程中取消流,则要确保使世界保持一致状态。例如,如果您正在构建某些东西,则可能要丢弃资源,破坏任何部分聚合结果,关闭文件,通道,释放内存或拥有的任何其他资源,从而可能撤消更改或对其进行补偿。>
您可能需要阅读cleanup上的文档,以便您也可以考虑在反应式对象方面可以做什么。
Flux<String> bridge = Flux.create(sink -> {
sink.onRequest(n -> channel.poll(n))
.onCancel(() -> channel.cancel())
.onDispose(() -> channel.close())
});
答案 1 :(得分:2)
@Edwin的回答很准确。只要您不调用订阅,就不会取消任何内容,因为不会执行任何代码。
只是想添加一个示例以使其清楚。
public static void main(String[] args) throws InterruptedException {
List<String> lists = Lists.newArrayList("abc", "def", "ghi");
Flux<String> end = Flux.fromIterable(lists)
.delayElements(Duration.ofSeconds(3))
.map(String::toLowerCase)
.subscribe(System.out::println);
Thread.sleep(5000); //Sleeping so that some elements in the flux gets printed
subscribe.dispose();
Thread.sleep(10000); // Sleeping so that we can prove even waiting for some time nothing gets printed after cancelling the flux
}
但是我想说一种更简洁的方法(函数方法)是利用takeUntil
或take
之类的函数。例如,在上述示例中,我也可以像这样停止流。
List<String> lists = Lists.newArrayList("abc", "def", "End", "ghi");
Flux.fromIterable(lists).takeUntil(s -> s.equalsIgnoreCase("End"))
.delayElements(Duration.ofSeconds(3))
.map(String::toLowerCase)
.subscribe(System.out::println);
或
List<String> lists = Lists.newArrayList("abc", "def", "ghi");
Flux.fromIterable(lists).take(2)
.delayElements(Duration.ofSeconds(2))
.map(String::toLowerCase)
.subscribe(System.out::println);