Kotlin сопрограммы - запустить другое задание, если через некоторое время первое не закончится - PullRequest
0 голосов
/ 26 февраля 2019

Я использую сопрограммы 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 Ответ

0 голосов
/ 26 февраля 2019

Я рекомендую использовать выражение 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 может измениться в будущих версиях библиотеки

...