Возвращаемое значение только быстрее сопрограммы - PullRequest
5 голосов
/ 11 июля 2019

Как я могу запустить несколько сопрограмм параллельно и вернуть только значение того, которое заканчивается первым?

Реальный сценарий, у меня есть два источника данных - База данных и Служба API . Мне все равно, откуда берутся данные, мне просто нужно это быстро. Как я могу запросить как База данных , так и Служба API и отменить другой запрос после его завершения?

В мире RxJava это будет равно Оператор Amb . Как мне добиться подобного поведения, используя сопрограммы?

Ответы [ 2 ]

1 голос
/ 12 июля 2019

Я придумал следующую реализацию:

suspend fun getFaster(): Int = coroutineScope {
    select<Int> {
        async { getFromServer() }.onAwait { it }
        async { getFromDB() }.onAwait { it }
    }.also {
        coroutineContext.cancelChildren()
    }
}

coroutineScope действует как родительский элемент для всех асинхронных вызовов, выполняемых внутри.После завершения select мы можем просто отменить остальные.

1 голос
/ 11 июля 2019

Вы можете использовать select, чтобы написать свой собственный оператор amb. Примерно так:

suspend fun <T> amb(vararg jobs: Deferred<T>): T = select {
    fun cancelAll() = jobs.forEach { it.cancel() }

    for (deferred in jobs) {
        deferred.onAwait {
            cancelAll()
            it
        }
    }
}

Подробнее о select выражение можно прочитать здесь

...