如何使用kotlinx-coroutines-reactive处理空方案?

时间:2018-02-05 07:16:56

标签: kotlin kotlinx.coroutines

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

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

如果没有人可以通过人员ID找到,则此调用将抛出NoSuchElementException并且此异常无法直接在用户代码中处理。而Spring MVC ExceptionHandler无法将此异常转换为用户友好的响应。

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方式来处理这种情况?

3 个答案:

答案 0 :(得分:1)

Kotlin中没有标准的Optional包装器。您可以使用the let function来处理此类情况:

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

如果await-expression的计算结果为默认null,则let调用也将计算为null。如果您需要处理这种情况,可以使用Elvis operator

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

答案 1 :(得分:1)

如果您正在以功能方式进行编程,那么绝对可以使用Optional包装器。

如果您希望通过函数式编程来解决问题,可以选择具有ArrowOption数据类型的Try用于此目的。

使用?.let是另一种选择,但它无法帮助您进行反应式编程。

ReactiveX中还有Notification类,如果您正在执行Railway Oriented Programming,它将允许您处理错误的情况。

答案 2 :(得分:0)

最近的awaitFirstOrNull()版本0.22.2中提供了扩展程序kotlinx.coroutines。请参阅此PR

取自发行说明:

  

反应:已添加awaitFirstOrDefaultawaitFirstOrNull个扩展程序(请参阅#konrad-kaminski的#224,PR)。