Hi everyone! My first post in here! I’m trying t...
# coroutines
n
Hi everyone! My first post in here! I’m trying to recreate the
throttleLatest
RX operator. I have the following:
Copy code
/**
 * Emits the next item emitted by a reactive source, then periodically emits the latest item
 * (if any) when the specified timeout elapses between them.
 *
 * <https://github.com/ReactiveX/RxJava/wiki/Filtering-Observables#throttlelatest>
 */
fun <E> ReceiveChannel<E>.throttleLatest(
    wait: Long = 1_000,
    context: CoroutineContext = Dispatchers.Default
): ReceiveChannel<E> = GlobalScope.produce(context) {
    var currentData: E? = null
    val tick = ticker(initialDelayMillis = 0, delayMillis = wait)

    while (!isClosedForReceive) {

        select<Unit> {
            tick.onReceiveOrNull {
                currentData?.let {
                    send(it)
                }
            }
            onReceiveOrNull {
                if (currentData == null) {
                    it?.let {
                        send(it) // send first time
                    }
                }
                currentData = it
            }
        }
    }
    tick.cancel()
}
My unit test:
Copy code
/**
     *  -A----B-C-------D--------|-->
     *  -a------c---1s
     *               ---d------1s
     *                          -|-->
     *  -A---------C-----------D-|-->
     */
    @Test
    fun throttleLatestTest() = runBlocking {
        val channel = Channel<String>()

        launch {
            channel.send("A") // Emit the first item
            channel.send("B") // Not the latest, so won't emit
            channel.send("C") // Since this is the last one before the 1s delay, this will be sent

            delay(1000)
            channel.send("D") // Emit this on the next tick
            delay(1000) // to keep the thread alive longer
            channel.close()
        }
        val expected = listOf<String>("A", "C", "D")
        val actual = channel.throttleLatest(1000).toList()
        println(actual)
        assertEquals(expected, actual)
    }
This works fine, but I was wondering if anyone could see any improvements on it? I feel like it’s just not perfect.