如何从Mono <a> on error?

时间:2018-04-18 11:07:59

标签: java reactive-programming project-reactor reactive-streams

Let's say i have the following chain:

public Mono<B> someMethod( Object arg ) {
  Mono<A> monoA = Mono.just( arg ).flatMap( adapter1::doSomething );
  // success chain
  return monoA.map( B::buildSuccessResponse );
}

But in case of error i need to return different type of B, let's say, B.buildErrorResponse( a ). Any onError / doOnError methods can return only original Mono type (A), but not the one I need to return (B). How to return different Mono type in case of error?

3 个答案:

答案 0 :(得分:1)

public Mono<B> someMethod( Object arg ) {
  Mono<A> monoA = Mono.just( arg ).flatMap( adapter1::doSomething );

  return monoA
   .map( B::buildSuccessResponse )
   .onErrorResume({ Throwable e ->
      return  Mono.just(B.buildSuccessResponse(e));
   }); // if there is no error, `onErrorResume` is effectively doing nothing
}

下面是一个简单的测试,您可以用来测试行为

    public static void main(String[] args) {
        Mono.just(1)
                .doOnNext(x -> {
                    throw new RuntimeException("some error from previous operation");
                }) //comment this out if you want to simulate successful response
                .map(String::valueOf)
                .onErrorResume(e -> Mono.just("error response"))
                .subscribe(System.out::println);
    }

答案 1 :(得分:0)

public Mono<B> someMethod(Object arg) {
    return Mono.just(arg)
            .flatMap(adapter1::doSomething)
            .onErrorResume(throwable -> throwable instanceof Exception,
                           throwable -> Mono.just(B.buildErrorResponse(throwable)))
            .map(B::buildSuccessResponse);
}

onErrorResume将捕获错误信号,如果它被抛入上游并将用新流替换所有该流(上游):Mono.just(B.buildErrorResponse(throwable))

关于someMethod逻辑的附注:

  1. 如果出现错误,此方法会发出next信号,表示error信号:B.buildErrorResponse(throwable)。这听起来不错,因为使用someMethod的人必须了解他从nextupstream)收到的someMthod信号是next还是{{1}信号error。相反,让if-condition返回实际的someMethod信号,用户将通过识别例如error中的错误来根据需要对该错误做出反应。

  2. 我对onErrorResume有相同的论据。

  3. 可以使用B::buildSuccessResponse替换以下代码:Mono.just(arg).flatMap(adapter1::doSomething)

  4. 总而言之,最终的代码将被重构为:

    adapter1.doSomething(arg)

答案 2 :(得分:0)

您可能要检出的方法是:onErrorResume(Throwable,Mapper)或onErrorResume(Predicate)

例如,您的代码可能如下所示:

public Mono<B> someMethod( Object arg ) {
  Mono monoA = Mono.just( arg ).flatMap( adapter1::doSomething );
  return monoA.onErrorResume({ Throwable e ->
      return B::buildSuccessResponse
  });
}

在这种情况下,onErrorResume将处理从adapter1 :: doSomething发出的任何错误。请记住,当发出错误时-在后续的Monos上将不再调用“ map”,“ flatMap”或任何其他方法,因为错误将被传递,而不是预期的对象。

然后您可以简单地将所有链接看起来像这样:

public Mono<B> someMethod( Object arg ) {
  return Mono.just( arg ).flatMap( adapter1::doSomething ).onErrorResume({ Throwable e ->
      return B::buildSuccessResponse
  });
}

请记住,所有以'do'开头的方法(例如'doOnError')都将执行提供的闭包,而不修改'emited'对象。