Chain kotlin流取决于结果状态

Chain kotlin流取决于结果状态,kotlin,kotlin-coroutines,flow,kotlin-flow,Kotlin,Kotlin Coroutines,Flow,Kotlin Flow,我正在寻找实现以下逻辑的最“干净”的方法: 我有N个方法,每个人都返回流(类型不同) 我想链接这些方法,所以如果1返回Result.Success,那么调用第二个,依此类推 最明显的方法是: methodA().map { methodAResult -> when (methodAResult) { is Result.Success -> { methodB(methodAResult).map { methodBResult ->

我正在寻找实现以下逻辑的最“干净”的方法:

  • 我有N个方法,每个人都返回流(类型不同)
  • 我想链接这些方法,所以如果1返回Result.Success,那么调用第二个,依此类推
最明显的方法是:

methodA().map { methodAResult ->
  when (methodAResult) {
    is Result.Success -> {
      methodB(methodAResult).map { methodBResult ->
        when (methodBResult) {
          is Result.Success -> {
            methodC(methodAResult).map { methodCResult ->
              when (methodCResult) {
                is Result.Success -> TODO()
                is Result.Failure -> TODO()
              }
            }
          }
          is Result.Failure -> TODO()
        }
      }
     }
     is Result.Failure -> TODO()
   }
 }

但它看起来像一个著名的“回调地狱”。你知道如何避免它吗?

我认为在这个用例中,你可能应该使用
suspend
函数,并使用
await()

错误应该通过所描述的异常进行传递。

我相信这可以通过以下方式消除:

methodA().transform{methodAResult->
何时(methodAResult){
is Success->methodB(methodAResult).collect{emit(it)}
是故障->TODO()
}
}.transform{methodBResult->
何时(methodBResult){
is Success->methodC(methodBResult).collect{emit(it)}
是故障->TODO()
}
}.transform{MethodResult->
何时(MethodResult){
是成功->待办事项()
是故障->TODO()
}
}

对由Маааааааааааааа

    methodA()
        .flatMapMerge {
            when (it) {
                is Result.Success -> methodB(it)
                is Result.Failure -> emptyFlow()
            }
        }.flatMapMerge {
            when (it) {
                is Result.Success -> methodC(it)
                is Result.Failure -> emptyFlow()
            }
        }.collect {
            when (it) {
                is Result.Success -> TODO()
                is Result.Failure -> TODO()
            }
        }

将一个流的输出合并到另一个流是flatMap的目标,因此使用flatMap看起来更干净一些

如果这个结果类有一个
映射
折叠
,或者
getOrNull
类型方法,那么可以进一步清理这个方法,并删除when块


另外,如果您需要传播收集失败,那么您可以使用只输出所需失败的流来替换对emptyFlow的调用。

u不能在流上使用Wait,正如我所写的,他需要用挂起函数来替换流。这是两种不同的情况。流允许我从“发布者”那里获得“更新”,暂停-用于运行“繁重”的工作。你是对的,流通常用于变量而不是函数,所以我没有注意到。首先,您可能会在成功时丢失
和失败时丢失
而不是
when
语句。我还发现很难理解用例。如果你能提供一个例子,也许我能给你一个更好的答案。假设你有一个用例来添加一个新事件。要添加新事件,您应该检查事件位置是否可用(从位置存储库返回结果流的fun),然后检查选项(预定义类型的事件)是否可用(从选项存储库返回结果流的fun),依此类推。它们没有按特定顺序提到,但必须尊重结果对象(假设位置检查返回Result.Failure,那么我们不需要等待来自不同存储库的其他结果-选项等等)是的,这看起来像我需要的,但是Result.Failure呢?在这种情况下,如何“停止”链条?upd:我想没有办法。明天将测试您的解决方案,希望您能接受它。如果您在failure分支中不发出任何信息,则不会继续处理此特定结果。如果这还不够,并且您希望在第一次失败后停止处理所有结果(甚至包括成功的结果),您可以定义一些布尔值
var thereWasFailureInMethodProcessing=false
,在failure分支中将其设置为
true
,并添加
If(thereWasFailureInMethodProcessing) return@transform
之前检查,当
块时检查。我建议使用flatMapMerge而不是transform,看起来更自然。对于失败案例,您可以返回空流或将失败结果转换为正确类型的结果,并返回新结果的流。甚至可以用fold调用来替换when块。@MichaelKrussel如果可能的话,您能像接受的答案一样提供代码示例吗