Return value only of the faster coroutine

拜拜、爱过 提交于 2019-12-30 05:00:07

问题


How can I run multiple coroutines in parallel and return only the value of the one that finishes first?

Real-life scenario, I have two data sources - Database and API service. I don't care where does the data originate from, I just need it fast. How can I query both Database and API service and cancel the other request when the one finishes?

In RxJava world this would be equal to Amb operator. How can I achieve similar behaviour using coroutines?


回答1:


I came up with following implementation:

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

The coroutineScope acts as a parent to all async calls performed within. After the select finishes we can just cancel the rest.




回答2:


You can use select to write your own amb operator. Something like that:

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

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

You can read more about select expression here



来源:https://stackoverflow.com/questions/56987792/return-value-only-of-the-faster-coroutine

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!