私はプロジェクトに新しいんだ原子炉や一般的な反応性プログラミングを。
私は現在、これに似たコードの一部に取り組んでいます:
Mono.just(userId)
.map(repo::findById)
.map(user-> {
if(user == null){
throw new UserNotFoundException();
}
return user;
})
// ... other mappings
この例では、おそらく愚かであり、このケースを実装するより良い方法は確かにありますが、ポイントは以下のとおりです。
それが使用することを間違っているthrow new
中で例外をmap
ブロックまたは私はこれを交換する必要がありますかreturn Mono.error(new UserNotFoundException())
?
やって、これらの2つの方法で任意の実際の違いはありますか?
例外スローの便利な方法として考えることができるいくつかの方法があります。
使用して要素を扱います Flux/Mono.handle
エラーまたは空のストリームをもたらすことができる要素の取り扱いを簡素化できた方法の一つは、オペレータですhandle
。
我々は問題を解決するためにそれを使用する方法を次のコードに示します:
Mono.just(userId)
.map(repo::findById)
.handle((user, sink) -> {
if(!isValid(user)){
sink.error(new InvalidUserException());
} else if (isSendable(user))
sink.next(user);
}
else {
//just ignore element
}
})
私たちが見ることができるように、.handle
オペレータは、合格するために必要なBiConsumer<T, SynchronousSink<>
要素を処理するために。ここでは、私たちのBiConsumerで2つのパラメータを持っています。最初のものは、第二の一方が上流からの元素でありSynchronousSink
、私たちは同期下流に要素を供給するのに役立ちます。このような技術は、我々の要素の処理の異なる結果を供給する能力を拡大しています。例えば、要素が無効である場合には、我々は同じにエラーを供給することができSycnchronousSync
、上流及び農産物キャンセルされたonError
下流に信号を。ターンでは、我々は、「フィルタ」と同じ使用できるhandle
演算子を。ハンドルたら、BiConsumer
実行され、どの要素が供給されていない、原子炉は、フィルタリングの一種であると私たちのために追加の要素を要求することを検討します。要素が有効である場合には最後に、我々は単純に呼び出すことができSynchronousSink#next
、我々は持つことになりますので、および下流私たちの要素を伝播するか、それにいくつかのマッピングを適用するhandle
としてmap
、ここでオペレータ。また、我々は、安全に無パフォーマンスへの影響と、その演算子を使用し、下流への送信素子又はエラーの検証などの検証の複雑な要素を提供することができます。
使用してスロー#concatMap
+Mono.error
マッピング中に例外をスローするためのオプションの一つは、交換することであるmap
とconcatMap
。その本質的には、concatMap
ほとんど同じことがないflatMap
し。唯一の違いは、あるconcatMap
時点で一つだけのサブすることができます。このような挙動は、内部実装に多くを簡素化し、パフォーマンスに影響を与えません。だから我々は、より機能的な方法で例外をスローするために、次のコードを使用することができます。
Mono.just(userId)
.map(repo::findById)
.concatMap(user-> {
if(!isValid(user)){
return Mono.error(new InvalidUserException());
}
return Mono.just(user);
})
無効なユーザーの場合は上記のサンプルでは、使用して例外を返しますMono.error
。同じ我々は使用してフラックスのために行うことができますFlux.error
。
Flux.just(userId1, userId2, userId3)
.map(repo::findById)
.concatMap(user-> {
if(!isValid(user)){
return Flux.error(new InvalidUserException());
}
return Mono.just(user);
})
注、両方のケースでは、我々は返す風邪一つだけの要素を持っているストリームを。原子炉では、そこケース返されたストリームでパフォーマンスを向上させる最適化のカップルは、ある寒いスカラーストリーム。したがって、フラックス/モノラル使用することをお勧めしますconcatMap
+ .just
、empty
、をerror
私たちは、より複雑なマッピングを必要とするとき、結果としてで終わる可能性というreturn null
かthrow new ...
。
注意!これまでにNULL値を許容するかどうかに入ってくるの要素をチェックしないでください。原子炉プロジェクトは、送信することはありません
null
、これは反応ストリーム仕様に違反するので(参照あなたのための値を規則2.13)したがって、もし場合にrepo.findById
はnullを返し、原子炉はあなたのためNullPointerExceptionがスローされます。
待って、なぜconcatMap
よりも優れていますかflatMap
?
その本質的に、flatMap
一度に実行される複数のサブからの要素をマージするように設計されています。それはflatMapは下ので、非同期ストリームを持っている必要があり、彼らは潜在的に複数のスレッド上でデータを処理できるか、それはいくつかのネットワーク呼び出し可能性があることを意味しています。続いて、このような期待の影響の実装は多くのでflatMap
、複数のストリームからのデータ(処理できなければならないThread
ため、別のストリームから排出(手段追加のメモリ割り当てが存在する場合、S)(同時データ構造の手段の使用)、エンキュー要素Queue
それぞれについてsはサブ)と反応ストリーム仕様規則(手段本当に複雑な実装)を違反していません。すべてのこれらの事実と私たちは、プレーンを交換するという事実を数えますmap
使用して例外をスローするより便利な方法への操作(同期である)Flux/Mono.error
(実行の同期を変更しません)私たちは、このような複雑な作業を必要としないと我々は非常に簡単に使用できるという事実につながるconcatMap
非同期処理のために設計されているが一度に単一ストリームのスカラー、冷たいストリームを処理するために、最適化のカップルを持っています。
使用して例外をスローします switchOnEmpty
だから、結果が空の場合に例外をスローする別のアプローチがあるswitchOnEmpty
演算子。次のコードは、我々はそのアプローチを使用することができます方法を示しています。
Mono.just(userId)
.flatMap(repo::findById)
.switchIfEmpty(Mono.error(new UserNotFoundExeception()))
私たちが見ることができるように、このケースではrepo::findById
持つべきMono
ではUser
戻り値の型として。場合したがって、User
インスタンスが見つかりません、結果ストリームが空になります。このように、原子炉は、代替呼び出しますMono
ように指定、switchIfEmpty
パラメータを。
であるとして、あなたの例外をスロー
これは、あまり読みやすいコードや悪い習慣(としてカウントすることができ、私自身の意見)が、プロジェクトの原子炉であるとして、あなたの例外をスローすることができます。缶は反応ストリーム仕様に(違反するので、何らかの方法でやったとしても、かかわらず、この文脈で違反フードの下、あなたのオペレータがあるので、意味的な観点からSubscriber
のチェーンでSubscriber
、したがって、S -意味的に、ラムダに例外をスローすると、投げにマッピングすることができで例外onNext
違反する方法スペックのルール2.13)。原子炉は、あなたのためにスローされた例外をキャッチして、それを伝播しますので、onError
あなたの下流への信号、それを行うことは禁止されていません。
持ち帰り
- 使用し
.handle
、複雑な要素の処理を提供するために、オペレータ - 使用
concatMap
+Mono.error
私たちがマッピング中に例外をスローする必要があるが、このような技術は、非同期要素処理の例のために最も適しています。 - 使用
flatMap
+Mono.error
我々はすでに持っていたflatMap
場所に Null
戻り値の型がそのように代わりに禁止されているとして、null
あなたの下流にmap
予期しないでしょうonError
とNullPointerException
- 使用
switchIfEmpty
あなたには、いくつかの特定の関数を呼び出した結果がで終了した場合にはエラー信号を送信するために必要なすべての場合に空のストリーム