4

kotlinx-coroutines-reactive使org.reactivestreams.PublisherawaitXXX方法:

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

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

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

4

3 回答 3

4

OptionalKotlin中没有标准的包装器。您可以在这种情况下使用let功能

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

如果 await-expression 计算为 default null,则let调用也将计算为null。如果需要处理这种情况,可以使用Elvis 运算符:

.let {...} ?: throw IllegalStateException()
于 2018-02-05T07:38:39.710 回答
2

awaitFirstOrNull()在最近的0.22.2kotlinx.coroutines版本中提供了一个扩展。请参阅此公关

摘自发行说明:

反应式:添加awaitFirstOrDefaultawaitFirstOrNull扩展(参见#224,@konrad-kaminski 的 PR)。

于 2018-02-08T08:17:55.920 回答
1

Optional如果您以函数式方式编程,您绝对可以使用包装器。

如果你想用函数式编程来弄湿你的脚趾,你可以为此选择具有OptionTry数据类型的Arrow 。

使用?.let是另一种选择,但它对响应式编程没有多大帮助。

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

于 2018-02-05T09:58:21.227 回答