通过Flux.create / Flux.switchMap可变间隔

时间:2019-03-21 03:37:05

标签: java project-reactor

我需要一个基于用户输入变量的计时器。这是最小的示例:

Flux.<Integer> create(e -> {
   log.info("create"); // Never gets triggered
   e.next(2); // Sample user input: change to 2 second interval
})
   .switchMap(v -> Flux.interval(Duration.ofSeconds(v)))
   .startWith(Flux.interval(Duration.ofSeconds(1)))
   .subscribe(e -> log.info("subscribe: {}", e)); // This works

在上面:

  • 我创建了一个Flux<Integer>,它应根据用户输入发出东西(在上面它仅发出2),
  • 然后根据新间隔切换为使用switchMap
  • 从默认的1秒间隔开始

以上内容在switchMap部分下面起作用,即我看到它每秒记录一次“ subscribe:N”,但是“ create”没有被记录,并且e.next(2)也从未被调用。 / p>

为什么这不起作用?此用例是否有更好的解决方案?

1 个答案:

答案 0 :(得分:1)

如JavaDoc中所述,Flux#startWith添加给定序列。

自从您传递Flux.interval(Duration.ofSeconds(1))作为参数以来,它将无限地每秒发出一长串,并且您基于Flux.create的发布者将永远不会得到订阅。

但是,如果将其更改为:

.startWith(Mono.delay(Duration.ofSeconds(1)))

您也可以考虑将代码更改为:

Flux.<Integer> create(e -> {
   log.info("create");
   e.next(2);
})
   .startWith(1)
   .switchMap(v -> Flux.interval(Duration.ofSeconds(v)))
   .subscribe(e -> log.info("subscribe: {}", e));

在这里,我们在startWith块之后立即使用Flux.create,并让switchMap像对待其他任何信号一样处理它。

另外,请注意,switchMap(v -> Flux.interval(Duration.ofSeconds(v)))的读法是:
“每N秒开始发射一次,其中N是最新发射的值”

如果只需要“延迟”一次,请考虑在此处也使用Mono.delay