所以我有一个Flux<Foo>
,我想将每个Foo
映射到Baz
。问题是,getBaz(Foo foo)
可能会抛出IOException
。
所以我考虑使用Mono<Baz> getBazRx(Foo foo)
方法,该方法在发生异常的情况下将返回Mono.just(baz)
或Mono.empty()
。
然后将以Flux<Mono<Baz>>
结尾,从而提醒Optional<T>
容器。
在Spring Reactor中是这样吗?如何正确食用?
答案 0 :(得分:2)
在反应流中,通常通过从流中删除不存在的元素(例如,空Mono
或元素被删除的Flux
)来处理“可选”,而不是使用{{ 1}},Flux<Optional>
或Mono<Optional>
调用同步Flux<Mono>
方法时,可以使用单个getBaz
操作,如下所示:
.handle
调用异步flux
.handle((foo, sink) -> {
try {
// propagate Baz down the stream
sink.next(getBaz(foo));
} catch (IOException e) {
// Since sink.next is not called here,
// the problematic element will be dropped from the stream
log.error(e);
}
})
方法(返回getBazRx
)时,可以在Mono
/ onErrorResume
/ flatMap
内使用flatMapSequential
,像这样:
concatMap
(或者您可以将flux
.flatMap(foo -> getBazRx(foo)
.onErrorResume(t -> {
log.error(t);
return Mono.empty();
}))
移到.onErrorResume
内,具体取决于您要捕获并忽略异常的位置)
此外,由于您在问题中提到了它...如果要创建将.getBazRx
包裹起来的getBazRx
,则如果{ {1}}可能会阻止:
getBaz
该实现实际上只是一个同步方法模拟一个异步方法。它有两个问题:
getBaz
Mono<Baz> getBazRx(Foo foo) {
// BAD!!!
try {
return Mono.just(getBaz(foo));
} catch (IOException e) {
return Mono.error(e) // or Mono.empty() if you want to ignore
}
}
被阻止,您最终可能会阻止事件循环相反,您应该将工作推迟到订阅了单声道后,然后在用于阻止操作的Mono
上运行任何阻止操作,如下所示:
getBaz
答案 1 :(得分:0)
由于要跳过错误(例如仅记录错误),因此可以使用onErrorContinue
。另外,由于getBaz
引发了一个已检查的异常,因此我们需要捕获它,并return
(而不是抛出)一个RuntimeException
。 Reactor有一个实用程序方法可以执行此Exceptions.propagate
:
flux
.map(foo -> {
try {
return getBaz(foo);
} catch (IOException e) {
return Exceptions.propagate(e);
}
})
.onErrorContinue(RuntimeException.class, (t, b) -> log.error(t))
.subscribe(baz -> log.info("Read value {}", baz));