我正在使用Kotlin协程从服务器获取数据,并将递延的时间传递给其他功能。万一服务器在2000毫秒内未给出答案,我想从本地Room DB中检索对象(如果它存在于本地数据库中),但是如果我最终从服务器接收到数据,我想保存在在本地数据库中供将来调用。我该如何实现?我考虑过使用withTimeout,但是在这种情况下,超时后无需等待服务器的响应。
override fun getDocument(): Deferred<Document> {
return GlobalScope.async {
withTimeoutOrNull(timeOut) {
serverC.getDocument().await()
} ?: dbC.getDocument().await()
}
}
我想到的一个主意:
fun getDocuments(): Deferred<Array<Document>> {
return GlobalScope.async {
val s = serverC.getDocuments()
delay(2000)
if (!s.isCompleted) {
GlobalScope.launch {
dbC.addDocuments(s.await())
}
val fromDb = dbC.getDocuments().await()
if (fromDb != null) {
fromDb
} else {
s.await()
}
} else {
s.await()
}
}
}
答案 0 :(得分:1)
我建议使用select
库中的kotlinx.coroutines
表达式。
https://kotlinlang.org/docs/reference/coroutines/select-expression.html
fun CoroutineScope.getDocumentsRemote(): Deferred<List<Document>>
fun CoroutineScope.getDocumentsLocal(): Deferred<List<Document>>
@UseExperimental(ExperimentalCoroutinesApi::class)
fun CoroutineScope.getDocuments(): Deferred<List<Document>> = async {
supervisorScope {
val documents = getDocumentsRemote()
select<List<Document>> {
onTimeout(100) {
documents.cancel()
getDocumentsLocal().await()
}
documents.onAwait {
it
}
}
}
}
通过网络中的onAwait
信号或超时来恢复选择表达式。在这种情况下,我们将返回本地数据。
您可能还希望分批加载文档,因为Channel
可能也有帮助
https://kotlinlang.org/docs/reference/coroutines/channels.html
最后,我们在示例中使用了kotlinx.coroutines的实验性API,函数onTimeout
在库的未来版本中可能会发生变化