基于对挂起函数的调用构建流程结果

Stu*_*uck 5 kotlin kotlin-coroutines

我正在学习协程,需要一些帮助来理解基本用例。

实现一个非阻塞方法:

  • 从(反应式)数据库中获取单个项目
  • 根据该项目的时间戳确定范围(即该项目所在的月份)
  • 获取该月的所有项目
  • 返回项目为Flow

方法

因为它必须返回一个Flow我不会使用的suspend(就像我返回单个项目时一样)。返回Flowsuspend(哪种返回 a Mono)最常见的是互斥的,对吗?

所以我想出了这个签名:

override fun getHistory(beforeUtcMillisExclusive: Long): Flow<Item>
Run Code Online (Sandbox Code Playgroud)

尝试实施:

val itemInNextPeriod = itemRepository.findOneByTimestampLessThan(beforeUtcMillisExclusive)
if (itemInNextPeriod == null) {
  return emptyFlow()
} else {
  val range = calcRange(itemInNextPeriod.timestamp)
  return itemRepository.findByTimestampGreaterThanEqualAndTimestampLessThan(range.start, range.end)
}
Run Code Online (Sandbox Code Playgroud)

这给了我第一行:

挂起函数“findOneByTimestampLessThan”只能从协程或另一个挂起函数调用

我理解这里不允许我们调用挂起函数的问题,并且当已经返回流时,IntelliJ“添加挂起”提出的解决方案没有意义。

所以,从这个问题我得到了使用的想法return flow {...}

return flow {
  val itemInNextPeriod = itemRepository.findOneByTimestampLessThan(beforeUtcMillisExclusive)
  if (itemInNextPeriod == null) {
    return@flow
  } else {
    val range = calcRange(itemInNextPeriod.timestamp)
    return@flow itemRepository.findByTimestampGreaterThanEqualAndTimestampLessThan(range.start, 
  range.end)
  }
}
Run Code Online (Sandbox Code Playgroud)

第二个存储库调用findByTimestampGreaterThanEqualAndTimestampLessThan返回Flow<Item>,我不明白为什么我不能返回它。

此函数必须返回单位类型不匹配类型的值。必填: 找到的单位: 流量

Мих*_*аль 6

return@flow从 lambda 返回,而不是从封闭函数返回。您需要将调用Flow返回的项目重新发送到您正在使用函数构建的项目findByTimestampGreaterThanEqualAndTimestampLessThan中:Flowflow

return flow {
    val itemInNextPeriod = itemRepository.findOneByTimestampLessThan(beforeUtcMillisExclusive)
    if (itemInNextPeriod != null) {
        val range = calcRange(itemInNextPeriod.timestamp)
        emitAll(itemRepository.findByTimestampGreaterThanEqualAndTimestampLessThan(range.start, range.end))
    }
}
Run Code Online (Sandbox Code Playgroud)