如何处理 Spring reactor Mono 或 Flux 中的错误?

ace*_*ace 9 spring project-reactor reactive-streams

我有以下代码重新调整 Mono<Foo>:

try {
    return userRepository.findById(id)  // step 1
        .flatMap(user -> barRepository.findByUserId( user.getId())  // step 2
        .map(bar-> Foo.builder().msg("Already exists").build())  // step 3
            .switchIfEmpty(barRepository.save(Bar.builder().userId(user.getId()).build())  // step 4
                .map(bar-> Foo.builder().msg("Created").build())   // step 5 
            ))
            .doOnError(throwable -> Mono.just(handleError(throwable)));
    } catch(Exception e) {

        log.error("from catch block");
        return Mono.just(handleError(e));

    }
Run Code Online (Sandbox Code Playgroud)

如果在步骤 1 中发生错误(例如,指定 id 的用户不存在),它会被 doOnError 或 try catch 块捕获还是这两个都没有?

如果在步骤 2、步骤 3、步骤 4 中发生错误,同样的问题。

什么是正确的代码,以便 doOnError 始终捕获错误并消除 try catch?

public interface UserRepository extends ReactiveMongoRepository<User, String>对 barRepository使用 相同的。

handleError(throwable) 只是执行 log.error(e.getMessage() 并重新调整 Foo。

And*_*tta 15

我认为第一个错误在标题中:“Mono or Flux”与错误处理无关。

  • Mono最多只能发出一项(流式传输一个元素)
  • Flux可以发出更复杂的东西(即列表)

要处理错误,您可以按照以下示例操作:

return webClient.get()
                .uri(url)
                .retrieve()
                .bodyToMono(ModelYouAreRetrieving.class)
                .doOnError(throwable -> logger.error("Failed for some reason", throwable))
                .onErrorReturn(new ModelYouAreRetrieving(...))
                .block();
Run Code Online (Sandbox Code Playgroud)


小智 5

DoOnError 只会执行副作用,并且假设 findById 会在失败时返回 Mono.Error() ,这样的事情应该可以工作。

return userRepository.findById(id)
    .flatMap ( user -> 
        barRepository.findByUserId(user.getId())
        .map((user,bar)-> Foo.builder().msg("Already exists").build())  
        .switchIfEmpty(barRepository.save(Bar.builder().userId(user.getId()).build())
        .map(bar-> Foo.builder().msg("Created").build())

    ))
    .onErrorReturn(throwable -> Mono.just(handleError(throwable)));
Run Code Online (Sandbox Code Playgroud)

只有在调用链的阻塞操作,或者在进入反应链之前发生运行时错误时,try catch 才会起作用。这些doOn操作不会修改链,它们仅用于副作用。由于flatMap需要生产者,因此您需要从调用中返回 Mono,在这种情况下,如果发生错误,则它只会传播错误。在所有反应链中,除非另有处理,否则错误将传播。