翻譯自:https://tech.io/playgrounds/929/reactive-programming-with-reactor-3/Error
Error
Description
Reactor ships with several operators that can be used to deal with errors:
propagate errors but also recover from it (eg. by falling back to a different
sequence or by retrying a new Subscription
).
Reactor有幾個可用于處理錯誤的運算符:傳播錯誤,但也可以從中恢復(例如,返回到不同的序列或重試新訂閱)。
Practice
In the first example, we will return a Mono
containing default user Saul
when an error occurs in the original Mono
, using the method onErrorReturn
.
If you want, you can even limit that fallback to the IllegalStateException
class. Use the User#SAUL
constant.
在第一個示例中,當原始Mono中出現錯誤時,我們將使用onErrorReturn方法返回一個包含默認user Saul的Mono。
如果需要,甚至可以將回退限制為IllegalStateException類。使用用戶#SAUL常數。
// Return a Mono<User> containing User.SAUL when an error occurs in the input Mono, else do not change the input Mono.
Mono<User> betterCallSaulForBogusMono(Mono<User> mono) {
return mono.onErrorReturn(User.SAUL);
}
Let's try the same thing with Flux
. In this case, we don't just want a single
fallback value, but a totally separate sequence (think getting stale data from a
cache). This can be achieved with onErrorResume
, which falls back to a Publisher<T>
.
讓我們用Flux做同樣的嘗試。在這種情況下,我們不僅需要單個回退值,還需要一個完全獨立的序列
(想想從緩存中獲取過時數據)。這可以通過onErrorResume實現,其依賴于Publisher<T>。
Emit both User#SAUL and User#JESSE whenever there is an error in the original FLux:
當原始Flux中出現錯誤時,發射User#SAUL和User#JESSE:
// Return a Flux<User> containing User.SAUL and User.JESSE when an error occurs in the input Flux, else do not change the input Flux.
Flux<User> betterCallSaulAndJesseForBogusFlux(Flux<User> flux) {
return flux.onErrorResume(throwable -> Flux.just(User.SAUL, User.JESSE));
}
Dealing with checked exceptions is a bit more complicated. Whenever some code that
throws checked exceptions is used in an operator (eg. the transformation function
of a map
), you will need to deal with it. The most straightforward way is to make
a more complex lambda with a try-catch
block that will transform the checked
exception into a RuntimeException
that can be signalled downstream.
處理選中的異常要復雜一些。每當在運算符(例如映射的轉換函數)中使用引發選中異常的代碼時,
您都需要處理它。最直接的方法是使用try-catch塊生成更復雜的lambda,該塊將檢查的異常轉換
為可以向下游發送信號的運行時異常。
There is a Exceptions#propagate
utility that will wrap a checked exception into a
special runtime exception that can be automatically unwrapped by Reactor subscribers
and StepVerifier
: this avoids seeing an irrelevant RuntimeException
in the stacktrace.
有一個Exceptions#propagate實用程序,它將選中的異常包裝成一個特殊的運行時異常,該異常可以由
Reactor訂閱者和StepVerifier自動展開:這可以避免在堆棧跟蹤中看到不相關的運行時異常。
Try to use that on the capitalizeMany
method within a map
: you'll need to catch
a GetOutOfHereException
, which is checked, but the corresponding test still expects
the GetOutOfHereException
directly.
嘗試在CapitalMany方法上在一個map內部使用:您需要捕獲一個GetOutOfHereException,該異常已被選中,
但相應的測試仍然直接預期GetOutOfHereException。
// Implement a method that capitalizes each user of the incoming flux using the
// #capitalizeUser method and emits an error containing a GetOutOfHereException error
Flux<User> capitalizeMany(Flux<User> flux) {
return flux.map(user -> {
try{
return capitalizeUser(user);
}catch (GetOutOfHereException e){
throw Exceptions.propagate(e);
}
});
}
User capitalizeUser(User user) throws GetOutOfHereException {
if (user.equals(User.SAUL)) {
throw new GetOutOfHereException();
}
return new User(user.getUsername(), user.getFirstname(), user.getLastname());
}