kotlinx-coroutines-reactive如何处理null场景?

kotlinx-coroutines-reactive使org.reactivestreams.Publisher拥有awaitXXX方法:

 val person = peopleReactiveRepository.findById(personId).awaitSingle() 

如果没有人可以通过人员IDfind,则此调用将引发NoSuchElementException,并且此exception不能直接在用户代码中处理 。 而Spring MVC ExceptionHandler不能将这个exception转换成用户友好的响应。

 java.util.NoSuchElementException: No value received via onNext for awaitSingle at kotlinx.coroutines.experimental.reactive.AwaitKt$awaitOne$$inlined$suspendCancellableCoroutine$lambda$1.onComplete(Await.kt:131) ~[kotlinx-coroutines-reactive-0.22.1.jar:na] at reactor.core.publisher.StrictSubscriber.onComplete(StrictSubscriber.java:123) ~[reactor-core-3.1.2.RELEASE.jar:3.1.2.RELEASE] at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onComplete(Operators.java:1327) ~[reactor-core-3.1.2.RELEASE.jar:3.1.2.RELEASE] at reactor.core.publisher.FluxHide$SuppressFuseableSubscriber.onComplete(FluxHide.java:137) ~[reactor-core-3.1.2.RELEASE.jar:3.1.2.RELEASE] at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:130) ~[reactor-core-3.1.2.RELEASE.jar:3.1.2.RELEASE] at reactor.core.publisher.MonoNext$NextSubscriber.onComplete(MonoNext.java:96) ~[reactor-core-3.1.2.RELEASE.jar:3.1.2.RELEASE] at com.mongodb.reactivestreams.client.internal.ObservableToPublisher$1.onComplete(ObservableToPublisher.java:78) ~[mongodb-driver-reactivestreams-1.6.0.jar:na] 

我可以找出的一个方法如下:

 val person = peopleRepository.findById(personId).awaitFirstOrDefault(null) if (person == null) { // do something } 

但我不认为这是一个优雅的方式。 例如,可以提供一个名为awaitSingleOptional的方法。

有没有更好的Kotlin方式来处理这种情况?

如果您是以function方式进行编程,那么您肯定可以使用Optional包装器。

如果您想通过函数式编程让脚趾受潮,可以选择带有Option和Try数据types的Arrow 。

使用?.let是另一种选择,但对反应式编程无能为力。

ReactiveX中还有Notification类,如果你正在进行面向铁路的编程 ,它可以让你处理一个错误的场景。

Kotlin没有标准的Optional包装。 对于这种情况,您可以使用let函数 :

 val person = peopleRepository.findById(personId).awaitFirstOrDefault(null)?.let { // do } 

如果await-expression的计算结果为默认值null ,那么let调用也会计算为null 。 如果您需要处理这种情况,可以使用Elvis操作员 :

 .let {...} ?: throw IllegalStateException() 

扩展awaitFirstOrNull()已经在最近的kotlinx.coroutines版本0.22.2中可用 。 看到这个PR 。

从发行说明中获取:

awaitFirstOrDefault :添加了awaitFirstOrDefaultawaitFirstOrNull扩展(请参阅@ konrad-kaminski的#224,PR)。