kotlin 协程有带定时器的异步调用吗?

问题描述 投票:0回答:2

Kotlin 是否可以在协程中调用 async() 函数一段时间,并在时间完成后返回默认结果?

我发现可以只调用await,然后无限等待结果。

async {
        ...
        val result = computation.await()
        ...
}

但实际生产情况下,您需要返回默认结果或异常。在 Kotlin 协程中做某事的正确方法是什么?就像类似这样的东西:

async {
        ...
        val timeout = 100500
        val result: SomeDeferredClass = computation.await(timeout)
        if (result.isTimeout()) {
           // get default value
        } else {
           // process result
        }
        ...
}
kotlin coroutine
2个回答
20
投票

您可以使用

withTimeout
功能。超时时它会抛出
CancellationException
。您可以捕获此异常并返回默认值。

类似这样的:

async {
    ...
    val timeout = 100500L

    try {
        withTimeout(timeout) {
            computation.await()
        }
        ...
    } catch (ex: CancellationException) {
        defaultValue
    }
}

您还可以使用

withTimeoutOrNull
函数,它会在超时时返回
null
。像这样:

async {
    ...
    val timeout = 100500L
    withTimeoutOrNull(timeout) { computation.await() } ?: defaultValue
}

这种方法无法让您区分超时和返回 null 的计算。这两种情况都会返回默认值。

有关更多信息,请参阅此处:https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md#timeout


5
投票

结合 Extensions 和 @marstran 解决方案,我找到了一个可能更适合您的要求的解决方案,即具有超时和默认值的

await
函数。我也认为这是一个更清洁的解决方案

只需定义扩展函数即可:

suspend fun <T> Deferred<T>.await(timeout : Long, defaultValue : T) =
    withTimeoutOrNull(timeout) { await() } ?: defaultValue

您可以在任何地方使用它。而不是

async {
    ...
    val timeout = 100500L
    withTimeoutOrNull(timeout) { computation.await() } ?: defaultValue
}

你可以简单地做

async {
    val timeout = 100500L
    computation.await(timeout, defaultValue)
}
© www.soinside.com 2019 - 2024. All rights reserved.