android - Kotlin 协程 - 如果一段时间后第一个任务没有完成,则启动另一个任务
问题描述
我正在使用 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()
}
}
}
解决方案
我建议使用库中的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 的 Experimental API,该功能onTimeout
可能会在库的未来版本中发生变化
推荐阅读
- android - WebRTC - Android/iOS 中的屏幕共享
- node.js - Discord.js:如何检查是否是人工管理员?
- css - TinyMCE 通知自定义 CSS
- batch-file - 如何让我的 .bat 脚本每 5 分钟运行一次?
- linux - 为什么即使禁用了 d-cache 也需要 DMB 屏障
- c++ - 带有 map_ANON 的 mmap 用于保存大量数据
- python - 在 Pandas 的组中填充以前的值
- javascript - 使用 timestampOffset 的 MediaSource API
- python - 在 Heroku 上托管时,Selenium 应用程序重定向到 Cloudflare 页面
- clojure - 无法在 cljs+clj 项目中运行 clj 文件导致“找不到”