Kotlin协程 - 如果在一段时间后第一个没有完成,则开始另一个任务

问题描述 投票:3回答:1

我正在使用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()
        }
    }
}
android database kotlin coroutine kotlin-coroutines
1个回答
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

            }
        }
    }
}

select表达式使用来自网络的onAwait信号或超时恢复。在这种情况下,我们返回本地数据。

您可能也希望以块的形式加载文档,因为Channels可能也有帮助https://kotlinlang.org/docs/reference/coroutines/channels.html

最后,我们在示例中使用了kotlinx.coroutines的实验API,函数onTimeout可能会在库的未来版本中发生变化

© www.soinside.com 2019 - 2024. All rights reserved.