Kotlin сопрограммы - запустить другое задание, если через некоторое время первое не закончится
Я использую сопрограммы Kotlin для получения данных с сервера, я передаю отложенные функции другим функциям. Если сервер не дает ответ в течение 2000 мс, я хотел бы получить объект из локальной БД комнаты (если он существует в локальной базе данных), но если я наконец получаю данные с сервера, я хотел бы сохранить их в в локальной БД для будущих звонков. Как я могу достичь этого? Я думал об использовании 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()
}
}
}
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
s тоже может помочь https://kotlinlang.org/docs/reference/coroutines/channels.html
И, наконец, мы используем экспериментальный API kotlinx.coroutines в примере, функция onTimeout
может измениться в будущих версиях библиотеки