链中发生错误时更新原始Mono。

时间:2019-11-12 14:15:41

标签: java project-reactor reactor

假设我有这样的东西:

Mono.just(a)
    .flatMap(...) // init
    // set fields on a if error occurs
    .flatMap(...) // finalize
    .subscribe();

在最后一个flatMap中,我将根据a中字段的值执行一些最终逻辑。特别是我需要知道init期间是否发生了错误...

所以我需要一种可以拦截错误并允许操作原始对象的方法。

如果我没记错的话,所有onError*方法都将返回原始对象,而不允许对其进行更新。

doOnError似乎也无法解决我的问题。

有没有办法实现我所需要的?

3 个答案:

答案 0 :(得分:2)

请记住,这是一连串的离散和(可能)异步步骤。进入步骤后,您获得的唯一上下文是上一步的输出,形式为onNextonCompleteonError信号,以及可以公开的所有Java核心语言功能给你。例如,如果您要在Flux lambda中组装内部flatmap,则Java使您可以访问该lambda的输入参数。

稍后可能是您所需的解决方案:一个可以获取原始值的范围。

这样,第一个flatMap可以作为封闭范围并处理名义和错误情况。像这样:

Mono<B> processed = Mono.just(a)
    .flatMap(a -> init(a)
        .onErrorResume(fallback(a))
    )
    .flatMap(...); // finalize
processed.subscribe();

//for illustration purposes, what process and fallback may typically look like:
Mono<B> init(A a) {
    return Mono.zip(
        asyncServiceStuff.process(a.stuff),
        asyncServiceOtherStuff.process(a.otherStuff),
        (bPart1, bPart2) -> new B(bPart1, bPart2)
    );
}

Mono<B> fallback(A original) {
    return Mono.just(new FallbackB(a.otherStuff));
}

也就是说,您似乎想从a创建后备广告,该后备广告已经可以在方法的 scope 中使用(理想情况下作为final输入参数或变量)。

答案 1 :(得分:0)

您丢失了以下事实:每个下一个反应式运算符都会为我们构建一个新的Mono实例。因此,如果再添​​加一个运算符,这对您来说并不重要:

/**
 * Simply emit a captured fallback value when any error is observed on this {@link Mono}.
 *
 * <p>
 * <img class="marble" src="doc-files/marbles/onErrorReturnForMono.svg" alt="">
 *
 * @param fallback the value to emit if an error occurs
 *
 * @return a new falling back {@link Mono}
 */
public final Mono<T> onErrorReturn(final T fallback) {

Mono.just(a)
    .flatMap(...)
    .onErrorReturn(fallbackValue)
    .flatMap(...)
    .subscribe();

您绝对可以对所有其他onError*进行调查,以查找可能的错误处理变体。

答案 2 :(得分:0)

Mono.just(a)
    .flatMap(...) // init
    // set fields on a if error occurs
    .onErrorResume(getFallbackMono(a))
    .flatMap(...) // finalize
    .subscribe();

...

private Mono<ClassOfA> getFallbackMono(ClassOfA a) {
    return Mono.just(getMutatedA(a));
}

.onErrorResume将使流返回到后备状态。在这里,您可以创建一个具有a突变值的新流。

.doOnError()是一个副作用运算符。我会用它来记录错误。