Reactor中的onErrorContinue?和?onErrorResume
前言
這似乎是 Reactor 的熱門(mén)搜索之一,至少當(dāng)我在谷歌中輸入 onErrorContinue 時(shí),onErrorResume 會(huì)在它旁邊彈出。讓我把我的測(cè)試代碼和我的一些解釋粘貼在下面。
1 基礎(chǔ)功能
這是一個(gè)簡(jiǎn)單的函數(shù),將 5 個(gè)連續(xù)的數(shù)字分別乘以 2,然后相加,當(dāng) i==2 時(shí)拋出一個(gè)異常:
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
用返回內(nèi)容替換 Flux,因此在 2 之后的數(shù)據(jù)不會(huì)被處理。唯一值得一提的是,onErrorResume()
不必馬上在錯(cuò)誤之后捕獲異常。在 onErrorContinue()
的官網(wǎng)文檔中(onErrorContinue),只有 onErrorContinue()
強(qiáng)調(diào)了了 upstream 關(guān)鍵詞,但顯然,它還有其他含義。
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
會(huì)丟棄錯(cuò)誤數(shù)據(jù) 2, 然后繼續(xù)數(shù)字 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
這樣的結(jié)果,你想到了嗎?onErrorContinue()
會(huì)在 onErrorResume()
得到錯(cuò)誤之前處理這個(gè)錯(cuò)誤。當(dāng)兩個(gè)錯(cuò)誤處理函數(shù)在同一個(gè)函數(shù)中的時(shí)候很明顯,但是當(dāng)你的函數(shù)中只有 onErrorResume()
,而一些調(diào)用者實(shí)際上有 onErrorContinue()
時(shí),你的 onErrorResume()
沒(méi)有被調(diào)用的原因可能就不那么明顯了。
5 使用 onErrorResume() 模擬 onErrorContinue()
有些博客建議我們完全不用 onErrorContinue()
,且在所有場(chǎng)景中僅用 onErrorResume()
。但是上述示例已經(jīng)展示了它們會(huì)產(chǎn)生不同的結(jié)果。那我們?cè)趺磳?shí)現(xiàn)呢?
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(); }
因此,本質(zhì)上是將可能在 flatMap 或 concatMap 中拋出錯(cuò)誤的操作包裝起來(lái),并在其上使用 onErrorResume()
。這樣,它會(huì)產(chǎn)生相同的結(jié)果:
input=1
input=2
onErrorResume
input=3
input=4
input=5
sum=26
6 使用 onErrorResume() 和下游的 onErrorContinue() 模擬 onErrorContinue()
有時(shí)候,onErrorContinue() 放在調(diào)用程序中,您無(wú)法控制它。但你仍然需要 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() ——這會(huì)阻塞 onErrorContinue(),這樣它就不會(huì)在 onErrorResume() 之前占用錯(cuò)誤。嘗試刪除 onErrorStop(),你會(huì)看到 onErrorContinue() 在 onErrorResume 之前彈出。
到此這篇關(guān)于Reactor中的onErrorContinue 和 onErrorResume的文章就介紹到這了,更多相關(guān)Reactor onErrorContinue 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Boot Swagger2使用方法過(guò)程解析
這篇文章主要介紹了Spring Boot Swagger2使用方法過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08Spring boot調(diào)用Oracle存儲(chǔ)過(guò)程的兩種方式及完整代碼
這篇文章主要給大家介紹了關(guān)于Spring boot調(diào)用Oracle存儲(chǔ)過(guò)程的兩種方式及完整代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08javaweb如何使用華為云短信通知公共類(lèi)調(diào)用
這篇文章主要介紹了javaweb使用華為云短信通知公共類(lèi)調(diào)用的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06MyBatis-Plus動(dòng)態(tài)表名的使用
本文主要介紹了MyBatis-Plus動(dòng)態(tài)表名的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04java基于正則表達(dá)式實(shí)現(xiàn)時(shí)間日期的常用判斷操作實(shí)例
這篇文章主要介紹了java基于正則表達(dá)式實(shí)現(xiàn)時(shí)間日期的常用判斷操作,簡(jiǎn)單說(shuō)明了正則表達(dá)式常用元字符含義并結(jié)合實(shí)例形式分析了java基于正則表達(dá)式針對(duì)常用日期時(shí)間格式的判斷操作技巧,需要的朋友可以參考下2017-10-10關(guān)于Hadoop中Spark?Streaming的基本概念
這篇文章主要介紹了關(guān)于Hadoop中Spark?Streaming的基本概念,Spark?Streaming是構(gòu)建在Spark上的實(shí)時(shí)計(jì)算框架,它擴(kuò)展了Spark處理大規(guī)模流式數(shù)據(jù)的能力,Spark?Streaming可結(jié)合批處理和交互式查詢(xún),需要的朋友可以參考下2023-07-07Java之next()、nextLine()區(qū)別及問(wèn)題解決
這篇文章主要介紹了Java之next()、nextLine()區(qū)別及問(wèn)題解決,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08