Hi guys. What is the equivalent of “onEachLatest” ...
# coroutines
g
Hi guys. What is the equivalent of “onEachLatest” operator in Flow? I need to cancel previously running suspend fun in onEach block
o
Not sure what operator you're referring to, I can't find that in reactor or rxjava -- but perhaps
collectLatest
is what you want?
Copy code
* The crucial difference from [collect] is that when the original flow emits a new value, [action] block for previous
 * value is cancelled.
m
Or
mapLatest
and simply returning the passed value.
Or just copy the implementation of
onEach
and add `Latest`:
Copy code
fun <T> Flow<T>.onEachLatest(action: suspend (T) -> Unit): Flow<T> = transformLatest { value ->
    action(value)
    emit(value)
}
👍 1
g
collectLatest is not exactly what I need. It’s a suspend function, and I’ve decided to switch to flow.onEach() {} . launchIn(scope) construction
I want to use this kind of pattern:
instead of scope.launch construction:
m
And
updateUI
can be safely canceled? If you get too many events you could also use
.conflate()
before
.onEach()
g
@Marc Knaup thx for your implementation but is it really missing in flow library?
m
A lot of operators could be added to the standard library 🙂
g
yes, updateUI can be canceled
I use debounce() instead of conflate
m
You could suggest adding it and provide a use case: https://github.com/Kotlin/kotlinx.coroutines/issues/new
I’m still undecided between
debounce
and
sample
.
debounce
causes an initial delay, doesn’t it?
Oh, but
sample
may be good for events but not for data 😅
A hybrid would be nice.
g
no,
debounce
takes the recent value in the time range
m
Yes, but it waits at least time range for that
So if you debounce 1 second you will get the first update at least in 1 second. That’s how I read the docs. But let me test
g
e.g. if user types “abcde” I will get value only when he stops typing
m
Yeah for typing it makes sense
For button clicks it won’t
g
@Marc Knaup and what do you think to use for button clicks? simple flow with
collectLatest{}
or
single()
?
m
None of the standard operators is suitable 😞
g
I am wondering what behavior do you want to achieve 😉
m
In RxJava it would be
throttleLatest
It would basically prevent two events (e.g. button clicks) that are too close together.
(you can do the same for
onEachLatest
😉)
b
@gabin you can use
mapLatest
as is (according to example you used)
Copy code
events()
   .mapLatest { event -> updateUI(event) }
   .launchIn(scope)
g
@bezrukov map has slightly different purpose. It converts 1 type to another. I don’t want to achieve this
b
in your case you will convert it to unit, and it doesn't matter. You can review collectLatest implementation, and it's done via mapLatest as well.
👍 2
if naming confuses you, you can add extension
onEachLatest(action: ..) =  mapLatest(action)
g
ok, thanks for proposition