How to get the first response of calling 5 request...
# coroutines
h
How to get the first response of calling 5 requests with Http call? The use case is sending 5 http requests then get the first response and cancel others. Any suggestions?
😶 1
j
Use select function. Register all deferred in it and after first receive cancel others.
👍 2
h
That's really helpful. Thank you so much.
r
@Jan Skrasek: Would you mind sharing a snippet of what that would look like? (For learning purposes.) I'm assuming you're referring to "Selecting deferred values", but am not familiar with the
select { }
function. Perhaps something like:
Copy code
// Ugly code
val requests = List<Deferred<String>>(5) {
    delay(Random.nextInt(0, 1000).toLong())
    async { "Response #$it" }
}
val response = select<String> {
    requests.withIndex().forEach { (index, deferred) ->
        deferred.onAwait { answer ->
            requests.forEach { it.cancel() }
            "Deferred $index produced answer '$answer'"
        }
    }
}
n
Alternative with
Flow
Copy code
withTimeout(limit) {
 merge(::func1.asFlow(),::func2.asFlow(),... ). first()
} (formatting not working on phone)
🙌 2
j
@Richard Gomez your's example seems reasonable, what's not working? You may take a look at some official samples: https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-core/jvm/test/guide/example-select-04.kt
r
your's example seems reasonable, what's not working?
Nothing in particular, just confirming that I have the right idea. 🙂 Is there a more idiomatic way to cancel a list of jobs than
requests.forEach(Job::cancel)
? I suppose you could run them in an ad-hoc context and cancel that once the first is completed.