Есть ли у Kotlin coroutines асинхронный вызов с таймером?

делает Котлин имеет возможность вызвать функцию async() в с сопрограмм некоторое время, ведьма вернет результат по умолчанию после завершения времени?

я обнаружил, что можно только вызвать await, и чем бесконечность ждать результата.

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

но реальный производственный случай, чем вам нужно, чтобы вернуть результат по умолчанию или исключение. Что такое правильный способ сделать что-то в Kotlin coroutines? Вроде что-то похожее на это:

async {
        ...
        val timeout = 100500
        val result: SomeDeferredClass = computation.await(timeout)
        if (result.isTimeout()) {
           // get default value
        } else {
           // process result
        }
        ...
}

2 ответов


можно использовать 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


сочетания обоих расширения и решение @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)
}