kotlin - 何时为调用 flow.single() 引发 NoSuchElementException
问题描述
假设我有一个这样的 API:
interface Foo {
val barFlow: Flow<Bar>
}
我像这样消费它:
class FooConsumer(private val foo: Foo) {
init {
CoroutineScope(Dispatchers.IO).launch {
val bar = foo.barFlow.single()
println("Collected bar: $bar)
}
}
}
根据文档,如果流为空,则可以抛出single
a 。NoSuchElementException
但是,这让我很困惑,因为对流的终端操作将“等待”要发出的流元素。那么调用如何single
知道流中没有元素呢?也许一个元素还没有发出?
我的意思是在引擎盖下,调用single
是在进行检查之前收集源流。因此,在执行 null 检查之前必须至少发出 1 个项目,因此 null 检查永远不应该成功并且NoSuchElementException
永远不应该抛出 a(对于流是不可为 null 类型的情况)。
那么NoSuchElementException
只有可空类型的流才有可能吗?
这是源代码single
:
/**
* The terminal operator, that awaits for one and only one value to be published.
* Throws [NoSuchElementException] for empty flow and [IllegalStateException] for flow
* that contains more than one element.
*/
public suspend fun <T> Flow<T>.single(): T {
var result: Any? = NULL
collect { value ->
if (result !== NULL) error("Expected only one element")
result = value
}
if (result === NULL) throw NoSuchElementException("Expected at least one element")
@Suppress("UNCHECKED_CAST")
return result as T
}
解决方案
NoSuchElementException
当 Flow 完成其发射而不发射单个元素时抛出。我现在能想到的一种情况是当您需要将集合转换为流源时。如果该集合为空并且您调用single
该 Flow,您将获得一个NoSuchElementException
.
这个例子可能看起来很荒谬,但你明白了:
val emptyListFlow = emptyList<Int>().asFlow()
launch {
val data = emptyListFlow.single()
}
推荐阅读
- spring-boot - API 调用的基本身份验证在 VPN 上不起作用
- mongodb - 如何更改列表中文档的顺序,MongoDB
- angular - 多次显示/隐藏组件角度
- android-studio - 未找到 Android Studio gradle 离线模式
- javascript - ChartJS: Changing Font-Size of X-Axis Labels on Line Chart
- python - 跟进问题:不均匀的html导致python列表不平衡
- python - Joining Pandas tables and keep NaN values if dates is null
- xsd - 是否可以在定义了其他方面 (XSD) 的元素中将默认值设置为属性?
- c++ - 如何阻止c ++舍入到最接近的整数
- amazon-s3 - 使用分区将 pyspark 数据帧写入 s3 位置