chr*_*der 7 kotlin kotlinx.coroutines
我想迭代一系列对象并返回异步调用的第一个非null.
重点是执行某种可能失败的异步操作,我有一系列的后备,我想按顺序尝试,一个接一个(即懒惰/不并行).
我试图做一些类似于我所做的事情,如果它是同步调用:
// ccs: List<CurrencyConverter>
override suspend fun getExchangeRateAsync(from: String, to: String) =
ccs.asSequence()
.map { it.getExchangeRateAsync(from, to) }
.firstOrNull { it != null }
?: throw CurrencyConverterException()
Run Code Online (Sandbox Code Playgroud)
IntelliJ抱怨:
暂停功能只能在协程体内调用
编辑:为了澄清,如果在List上映射,这可以正常工作,但我想看看我如何在序列上执行此操作.
所以我想这是因为地图lambda没有被暂停?但我不确定如何实际做到这一点.我尝试了许多不同的方法,但似乎都没有.我找不到任何例子.
如果我使用for带有异步块的循环以更加程序化的方式重写它,我可以使它工作:
override suspend fun getExchangeRateAsync(from: String, to: String) {
for (cc in ccs) {
var res: BigDecimal? = async {
cc.getExchangeRateAsync(from, to)
}.await()
if (res != null) {
return res
}
}
throw CurrencyConverterException()
}
Run Code Online (Sandbox Code Playgroud)
小智 5
我建议用流程替换序列。Flow api 和行为与 Sequence 几乎相同,但具有暂停选项。
https://kotlinlang.org/docs/reference/coroutines/flow.html
Run Code Online (Sandbox Code Playgroud)
代码:
override suspend fun getExchangeRateAsync(from: String, to: String) =
ccs.asFlow()
.map { it.getExchangeRateAsync(from, to) }
.firstOrNull { it != null }
?: throw CurrencyConverterException()
Run Code Online (Sandbox Code Playgroud)
您收到错误,因为Sequence默认情况下是惰性的,并且它map不是内联函数,因此未定义它的范围
Sequence您可以通过创建惰性协程列表来避免使用
// ccs: List<CurrencyConverter>
suspend fun getExchangeRateAsync(from: String, to: String) =
ccs
.map { async(start = CoroutineStart.LAZY) { it.getExchangeRateAsync(from, to) } }
.firstOrNull { it.await() != null }
?.getCompleted() ?: throw Exception()
Run Code Online (Sandbox Code Playgroud)
这不会给出任何错误并且似乎有效。但我不确定这是一种惯用的方式
| 归档时间: |
|
| 查看次数: |
648 次 |
| 最近记录: |