Reactor中的onErrorContinue 和 onErrorResume

 更新时间:2022年09月22日 15:01:13   作者:十二又十三  
这篇文章主要介绍了Reactor中的onErrorContinue 和 onErrorResume,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下

前言

这似乎是 Reactor 的热门搜索之一,至少当我在谷歌中输入 onErrorContinue 时,onErrorResume 会在它旁边弹出。让我把我的测试代码和我的一些解释粘贴在下面。

1 基础功能

这是一个简单的函数,将 5 个连续的数字分别乘以 2,然后相加,当 i==2 时抛出一个异常:

public static void main(String... args) {
      Flux.range(1,5)
              .doOnNext(i -> System.out.println("input=" + i))
              .map(i -> i == 2 ? i / 0 : i)
              .map(i -> i * 2)
              .reduce((i,j) -> i+j)
              .doOnNext(i -> System.out.println("sum=" + i))
              .block();
  }

显然,输出如下:

input=1
input=2
Exception in thread "main" java.lang.ArithmeticException: / by zero

2 只有 onErrorResume ()

public static void main(String... args) {
      Flux.range(1,5)
              .doOnNext(i -> System.out.println("input=" + i))
              .map(i -> i == 2 ? i / 0 : i)
              .map(i -> i * 2)
              .onErrorResume(err -> {
                  log.info("onErrorResume");
                  return Flux.empty();
              })
              .reduce((i,j) -> i+j)
              .doOnNext(i -> System.out.println("sum=" + i))
              .block();
  }

输出如下:

input=1
input=2
17:40:47.828 [main] INFO com.example.demo.config.TestRunner - onErrorResume
sum=2

正如官方文档描述(onErrorResume)的那样,onErrorResume 用返回内容替换 Flux,因此在 2 之后的数据不会被处理。唯一值得一提的是,onErrorResume() 不必马上在错误之后捕获异常。在 onErrorContinue() 的官网文档中(onErrorContinue),只有 onErrorContinue() 强调了了 upstream 关键词,但显然,它还有其他含义。

3 只有 onErrorContinue()

public static void main(String... args) {
  Flux.range(1,5)
          .doOnNext(i -> System.out.println("input=" + i))
          .map(i -> i == 2 ? i / 0 : i)
          .map(i -> i * 2)
          .onErrorContinue((err, i) -> {log.info("onErrorContinue={}", i);})
          .reduce((i,j) -> i+j)
          .doOnNext(i -> System.out.println("sum=" + i))
          .block();
}

输出:

input=1
input=2
17:43:10.656 [main] INFO com.example.demo.config.TestRunner - onErrorContinue=2
input=3
input=4
input=5
sum=26

显然,onErrorContinue 会丢弃错误数据 2, 然后继续数字 3 直到 5。

4 onErrorResume() 然后 onErrorContinue()

public static void main(String... args) {
    Flux.range(1,5)
            .doOnNext(i -> System.out.println("input=" + i))
            .map(i -> i == 2 ? i / 0 : i)
            .map(i -> i * 2)
            .onErrorResume(err -> {
                log.info("onErrorResume");
                return Flux.empty();
            })
            .onErrorContinue((err, i) -> {log.info("onErrorContinue={}", i);})
            .reduce((i,j) -> i+j)
            .doOnNext(i -> System.out.println("sum=" + i))
            .block();
}

输出和上面一样:

input=1
input=2
17:47:05.789 [main] INFO com.example.demo.config.TestRunner - onErrorContinue=2
input=3
input=4
input=5
sum=26

这样的结果,你想到了吗?onErrorContinue() 会在 onErrorResume() 得到错误之前处理这个错误。当两个错误处理函数在同一个函数中的时候很明显,但是当你的函数中只有 onErrorResume(),而一些调用者实际上有 onErrorContinue() 时,你的 onErrorResume() 没有被调用的原因可能就不那么明显了。

5 使用 onErrorResume() 模拟 onErrorContinue()

有些博客建议我们完全不用 onErrorContinue(),且在所有场景中仅用 onErrorResume()。但是上述示例已经展示了它们会产生不同的结果。那我们怎么实现呢?

public static void main(String... args) {
    Flux.range(1,5)
            .doOnNext(i -> System.out.println("input=" + i))
            .flatMap(i -> Mono.just(i)
                    .map(j -> j == 2 ? j / 0 : j)
                    .map(j -> j * 2)
                    .onErrorResume(err -> {
                        System.out.println("onErrorResume");
                        return Mono.empty();
                    })
            )
            .reduce((i,j) -> i+j)
            .doOnNext(i -> System.out.println("sum=" + i))
            .block();
}

因此,本质上是将可能在 flatMap 或 concatMap 中抛出错误的操作包装起来,并在其上使用 onErrorResume()。这样,它会产生相同的结果:

input=1
input=2
onErrorResume
input=3
input=4
input=5
sum=26

6 使用 onErrorResume() 和下游的 onErrorContinue() 模拟 onErrorContinue()

有时候,onErrorContinue() 放在调用程序中,您无法控制它。但你仍然需要 onErrorResume()。你该怎么办?

public static void main(String... args) {
    Flux.range(1,5)
            .doOnNext(i -> System.out.println("input=" + i))
            .flatMap(i -> Mono.just(i)
                    .map(j -> j == 2 ? j / 0 : j)
                    .map(j -> j * 2)
                    .onErrorResume(err -> {
                        System.out.println("onErrorResume");
                        return Mono.empty();
                    })
                    .onErrorStop()
            )
            .onErrorContinue((err, i) -> {log.info("onErrorContinue={}", i);})
            .reduce((i,j) -> i+j)
            .doOnNext(i -> System.out.println("sum=" + i))
            .block();
}

秘诀是在 onErrorResume() 代码块的末尾添加 onErrorStop() ——这会阻塞 onErrorContinue(),这样它就不会在 onErrorResume() 之前占用错误。尝试删除 onErrorStop(),你会看到 onErrorContinue() 在 onErrorResume 之前弹出。

到此这篇关于Reactor中的onErrorContinue 和 onErrorResume的文章就介绍到这了,更多相关Reactor onErrorContinue 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java实现两台服务器间文件复制的方法

    java实现两台服务器间文件复制的方法

    这篇文章主要介绍了java实现两台服务器间文件复制的方法,是对单台服务器上文件复制功能的升级与改进,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-01-01
  • SpringBoot整合JWT Token的完整步骤

    SpringBoot整合JWT Token的完整步骤

    JSON Web Token是目前最流行的跨域认证解决方案,适合前后端分离项目通过Restful API进行数据交互时进行身份认证,这篇文章主要给大家介绍了关于SpringBoot整合JWT Token的相关资料,需要的朋友可以参考下
    2021-09-09
  • java线程间通讯的一些方法总结

    java线程间通讯的一些方法总结

    这篇文章主要介绍了java线程间通讯的一些方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • Java实例化一个抽象类对象的方法教程

    Java实例化一个抽象类对象的方法教程

    大家都知道抽象类无法实例化,就无法创建对象。所以下面这篇文章主要给大家介绍了关于Java实例化一个抽象类对象的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧。
    2017-12-12
  • 异常点/离群点检测算法——LOF解析

    异常点/离群点检测算法——LOF解析

    这篇文章主要介绍了异常点/离群点检测算法——LOF解析,通过图解文字描述的方式详细的解析了该算法,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • Java+MySQL实现图书管理系统(完整代码)

    Java+MySQL实现图书管理系统(完整代码)

    这篇文章主要介绍了Java+MySQL实现图书管理系统(完整代码),本文给大家介绍的非常想详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • 自己动手写一个java版简单云相册

    自己动手写一个java版简单云相册

    这篇文章主要为大家分享了自己动手写的一个java版简单云相册,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-07-07
  • 通过实例解析Spring argNames属性

    通过实例解析Spring argNames属性

    这篇文章主要介绍了通过实例解析Spring argNames属性,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • springmvc json类型转换错误解决方案

    springmvc json类型转换错误解决方案

    这篇文章主要介绍了springmvc json类型转换错误解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • java时间相关处理小结

    java时间相关处理小结

    这篇文章介绍了java时间相关处理,有需要的朋友可以参考一下
    2013-11-11

最新评论