Thread
#reaktive
    Omar Mainegra

    Omar Mainegra

    2 years ago
    Hi everyone, I'm investigating an issue with
    debounce
    in iOS, for some reason is NOT waiting the
    timeout
    @Test
    fun `'debounce' using Main scheduler works`() {
        val timeout = 10L
        val time = getTimeMillis()
        val wasCalled = AtomicBoolean(false)
    
        observableOf(1, 2, 3, 4, 5)
            .debounce(timeout, mainScheduler)
            .subscribe { value ->
                val elapsed = getTimeMillis() - time
                assertTrue("Should have passed more than $timeout millis, but was $elapsed") { elapsed >= timeout }
                assertEquals(5, value)
    
                wasCalled.value = true
            }
    
        await(2*timeout.toInt())
        assertTrue("`subscribe` was not called") { wasCalled.value }
    }
    The test fails
    kotlin.AssertionError: Should have passed more than 10 millis, but was 1
    But it works with
    ioScheduler
    and
    computationScheduler
    ,
    also if
    delay
    is used instead of
    debounce
    it works as well. PS: The
    await
    functions just runs the current Loop:
    private fun await(millis: Int) {
        NSRunLoop.currentRunLoop.runUntilDate(NSDate.dateWithTimeInterval(millis.toDouble()/1000.0, NSDate.now))
    }
    Arkadii Ivanov

    Arkadii Ivanov

    2 years ago
    Hello, if I'm not missing something the subscribe block should be called with a single value
    5
    almost immediately after subsription. The output looks correct.
    This is your case:
    Omar Mainegra

    Omar Mainegra

    2 years ago
    Hi, thanks for the response, according to the doc (and the bubble diagram) there's an initial delay
    Arkadii Ivanov

    Arkadii Ivanov

    2 years ago
    Where do you see an initial delay?
    Omar Mainegra

    Omar Mainegra

    2 years ago
    Arkadii Ivanov

    Arkadii Ivanov

    2 years ago
    You mean the delay between first blue "1" and its emission?
    Omar Mainegra

    Omar Mainegra

    2 years ago
    The first element is emitted after the
    timeout
    as well
    Yes
    Arkadii Ivanov

    Arkadii Ivanov

    2 years ago
    But in your case the second element is emitted straightaway which "overrides" the first one
    Omar Mainegra

    Omar Mainegra

    2 years ago
    Yes, the seconds elements "resets" the timer, but it should be emitted after the timeout elapsed (This is what I expect)
    Arkadii Ivanov

    Arkadii Ivanov

    2 years ago
    No, as soon as items are emitted by upstream and the time between emissions is less than timeout, nothing will be emitted
    Basically every emission from upstream resets the timer. Emission to downstream is performed when the timer reaches timeout.
    Or when upstream completes
    Omar Mainegra

    Omar Mainegra

    2 years ago
    Exactly, and in my case is not when it reaches the timeout, but immediately
    Arkadii Ivanov

    Arkadii Ivanov

    2 years ago
    I don't understand
    Omar Mainegra

    Omar Mainegra

    2 years ago
    In any case, whatever element is emitted, it should be after the timeout (at least)
    Arkadii Ivanov

    Arkadii Ivanov

    2 years ago
    No, because upstream complets
    This forces debounce to emit
    Omar Mainegra

    Omar Mainegra

    2 years ago
    AHhh I see
    Good point, let me rewrite the test case
    Arkadii Ivanov

    Arkadii Ivanov

    2 years ago
    Yep, something like:
    observable<Int> { (1..5).forEach(it::onNext) }
    Without completion it should emit the last value after timeout
    Omar Mainegra

    Omar Mainegra

    2 years ago
    👏 Indeed
    Thanks
    Arkadii Ivanov

    Arkadii Ivanov

    2 years ago
    You are welcome