【发布时间】:2021-03-24 16:05:48
【问题描述】:
我已经构建了一个分片库,我正在尝试向它添加协程功能。在下面的 sn-p 中,它返回它找到的第一个 true 结果:
override fun emailExists(email: String): Boolean {
return runBlocking {
shards
.asyncAll { userDao.emailExists(email) }
.map { it.await() }
.firstOrNull { it }
} ?: false
}
shards.asyncAll 方法是:
fun <T> async(
shardId: Long,
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> T): Deferred<T> {
return scope.async(context, start) {
selectShard(shardId)
block()
}
}
fun <T> asyncAll(
shardIds: Collection<Long> = this.shardIds,
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> T): List<Deferred<T>> {
return shardIds.map { async(it, context, start, block) }
}
这可行,但它会查询分片以便返回,这意味着如果第一个分片需要很长时间才能返回并且它没有返回 true 但第二个分片立即返回值 @987654327 @只要第一个分片返回,我们仍在等待。有没有更好的方法来等待 Deferred<> 集合的值并按照它们返回的顺序处理它们,以便我可以尽早退出?
【问题讨论】:
-
理想情况下,有一种方法可以不使用 Flow。
-
我特别不想等待所有这些。
-
是的,对不起。
awaitAll适用于对第一个错误做出反应,但不适用于第一个结果。似乎没有内置的awaitAny或awaitFirst,但有this answer,您可以只专注于一个元素。
标签: multithreading kotlin kotlin-coroutines