If I have a channel, how can I “channel.take(5)“, ...
# coroutines
v
If I have a channel, how can I “channel.take(5)“, ie. get a list containing the 5 items I would get if I channel.receive() 5 times?
b
channel.take(5).toList()
v
Does not work: https://pl.kotl.in/imipXeoIe from what I can see,
channel.take
is marked with ObsoleteCoroutineAPI
r
1. You've forgot to close the channel when you're done with it. 2. You've created rendezvous channel without buffer, so as soon as you
send
to it, coroutine suspends till someone `receive`s a value, and in your case there is only one coroutine so noone would be able to consume values. So to make the code work, 1. Add
channel.close()
to the end, 2. Add
Unit
as the last statement (or don't use single-expression for your
main
with
runBlocking
) 3. Either create buffered channel (
Channel<Int>(10)
) or split the sending and receiving parts into concurrent coroutines, for example, by wrapping
repeat
in
launch { ... }
.
b
As well, ObsoleteCoroutineAPI doesn't make it any less valid until they provide the alternatives
Example using a
produce
coroutine and closing the channel when finished using it: https://pl.kotl.in/CTmfVmaR8 (since the
produce
coroutine only repeats
5
, it will automatically close the channel, so it's not necessary with that coroutine builder)
d
@r4zzz4k Conflated channels NEVER suspend on
send
Doesn't the Flow API have something for this?
r
@Dico yeah, that had to be rendezvous, not conflated -- my bad, thanks for pointing out!
v
Thanks for the discussion guys!
b
Definitely a typo there. Channels are Rendezvous by default :)
v
Guys! I managed to do it very nicely, just tiny modification from my original example. https://pl.kotl.in/sJFQEt0GO I had just forgotten to send to the channel from within a coroutine. Not totally clear to me why it makes such a difference though 🤔
b
Because concurrency is explicit in Kotlin coroutines. Without it, your
send
method suspends your method until something `receive`s it. Since you were doing
send
and
receive
in the same coroutine, the
send
was suspending your coroutine, which means it hung forever because no one else was going to receive.
Make sure that you close the channel when you are done with it. Otherwise, it's a memory leak waiting to happen
🙏 1
v
This makes it totally clear! Thank you @bdawg.io!!