【问题标题】:How to handle the null scenario with kotlinx-coroutines-reactive?如何使用 kotlinx-coroutines-reactive 处理空场景?
【发布时间】:2018-07-15 00:13:27
【问题描述】:

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

【问题讨论】:

标签: kotlin kotlinx.coroutines


【解决方案1】:

Kotlin 中没有标准的 Optional 包装器。对于这种情况,您可以使用the let function

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

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

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

【讨论】:

【解决方案2】:

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

如果您想通过函数式编程来沾沾自喜,您可以选择具有 OptionTry 数据类型的 Arrow

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

ReactiveX 中还有 Notification 类,如果你在做 Railway Oriented Programming,它可以让你处理错误的场景。

【讨论】:

  • 什么是可选的,我在 Kotlin JS 上?
  • 不,Optional 是 JDK 的一部分。 Option 是 Arrow 的一部分。
  • 什么是 Arrow,我也是从 Objective C 调用的?
  • 这个问题用 [kotlin] 和 [kotlinx.coroutines] 标记,所以我不知道 Objective C 可能如何参与。 Arrow 是一个函数式编程库,我的答案中有一个链接。
【解决方案3】:

在最近的kotlinx.coroutines 版本0.22.2 中提供了扩展awaitFirstOrNull()。看到这个PR

取自发行说明:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-26
    • 2021-11-23
    • 2012-02-28
    • 2014-05-07
    • 2023-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多