https://kotlinlang.org logo
#coroutines
Title
# coroutines
m

Maciek

07/20/2020, 11:50 AM
I've got two deferred values. I want to wait for both, execute something after one of them completes and cancel the other one, not yet completed. What'd be the mechanism to achieve it?
t

Tim Malseed

07/20/2020, 11:52 AM
If you can represent them with
Flow
, then I believe
Flow.zip
is the operator you’re looking for here
🙏 1
m

Maciek

07/20/2020, 11:54 AM
that's what I was looking for, thanks! I was thinking about saving the job in the field but that looked really ugly
👍 1
is there a way to complete/cancel a flow that's been received from the channel without affecting the underlying channel? I want to close the flow after first value. In order to use the zip operators from the case above
t

Tim Malseed

07/20/2020, 12:21 PM
Instead of
onEach()
, you could try
first()
k

Kroppeb

07/20/2020, 2:14 PM
j

julian

07/20/2020, 4:36 PM
zip
will wait for an emission from both flows. It alone doesn't allow you to race 2 flows and cancel the loser once you have a winner.
However if what you race is flows that emits flows, then your zip lambda could use a multi-threaded merge to emit. Then, downstream from the zip operator, using
first
would cancel all upstreams once you have a winner.
https://pl.kotl.in/VkjkbCk7I illustrates using
zip
to cancel upstreams without forcing
zip
to wait for emissions from both zipped streams.
l

louiscad

07/21/2020, 3:55 AM
I had this use case a while ago, and I implemented a function called
raceOf
where the winner coroutine cancels the others, and where its value is used. https://github.com/LouisCAD/Splitties/blob/017c21aaa03fc14859ea6b8e2500b3093f8dbc62/modules/coroutines/src/commonMain/kotlin/splitties/coroutines/Racing.kt#L29-52 The other code in the file supports the
race
function which allows to launch racers dynamically, if some coroutines need to join the race only based on some conditions.
🙌🏾 1
I use this a lot, especially with
awaitCancellation()
(which justs suspends until cancelled, returning
Nothing
) for UI code where multiple user actions are allowed in a scope/context.
t

Tim Malseed

07/21/2020, 3:58 AM
@julian From the zip docs
 The resulting flow completes as soon as one of the flows completes and cancel is called on the remaining flow
I took this to mean that it does not wait for both flows to emit. Am I misinterpreting the docs?
l

louiscad

07/21/2020, 4:01 AM
A flow completing is different from a flow emitting. Completion of a flow cannot happen while an element is being collected (but can before and after).
t

Tim Malseed

07/21/2020, 4:02 AM
Oh, of course. I mistook completion for emission. Thanks
j

julian

07/21/2020, 4:05 AM
@Tim Malseed
zip
waits for an emission from both flows being zipped before executing the lambda supplied to it. This lambda is the first opportunity one has to do anything with the flows. The next opportunity is downstream from the
zip
operator. Problem is, you can't cancel either flow from inside the `zip`'s lambda. And by the time you cancel downstream of
zip
, both flows have already emitted.
t

Tim Malseed

07/21/2020, 4:06 AM
Thanks - I was indeed misinterpreting the docs
👍🏾 1
5 Views