Skip to main content

Command Palette

Search for a command to run...

Chapter 12 : UseCase09 - debounce

Updated
3 min read

Let us now work on time-based control

debounce() waits for a quiet period before emitting a value.

If new values keep arriving quickly, it keeps resetting the timer. Only when emissions stop for a specified duration does the latest value get emitted.

REAL STOCK SCENARIO

A user types into a search box :

H

HE

HEL

HELI

HELIO

HELIOS

Say we have a list of 6000 stocks. Do we want to filter 6000 stocks on every keystroke?

Certainly not. We wait until the user stops typing. That is debounce()

What debounce() does

If values arrive faster than the debounce duration, they are ignored.

Only the latest value after a pause is emitted.

Let us checkout a working example from our stocks list.

package org.kotlinflowlearner.stockflow.usecases.uc09

import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.flow

/**
 * UC09DebounceStockSearch demonstrates how debounce()
 * waits for a pause before emitting the latest value.
 */
class UC09DebounceStockSearch {

    private fun simulatedSearchQueries(): Flow<String> = flow {

        emit("H")
        delay(100)

        emit("HE")
        delay(100)

        emit("HEL")
        delay(100)

        emit("HELI")
        delay(100)

        emit("HELIO")
        delay(100) //this pause is shorter than 500ms

        emit("HELIOS")
        delay(600) //this pause is longer than the debounce window of 500ms defined below

    }

    fun debouncedSearch() : Flow<String> = simulatedSearchQueries().debounce(500)
    }
package org.kotlinflowlearner.stockflow.usecases.uc09

import kotlinx.coroutines.runBlocking

fun main(){

    runBlocking {

        val useCase = UC09DebounceStockSearch()

        useCase.debouncedSearch().collect{
            query -> println("Processing search for: $query")
        }
    }
}

The output produced is

Processing search for: HELIOS

WHAT IS ACTUALLY HAPPENING

  • "H" is emitted.
    Debounce starts a 500ms timer.

  • After 100ms, "HE" arrives.
    The previous timer is cancelled. A new 500ms timer starts for "HE".

  • After 100ms, "HEL" arrives.
    Cancel timer again. Start new timer.

  • Same for "HELI".

  • Same for "HELIO".

  • Same for "HELIOS".

Now finally:

After emitting "HELIOS", we wait 600ms.

That exceeds 500ms. So the debounce timer completes. Now "HELIOS" is emitted downstream.

Key Insight

Let’s understand what debounce(500) really means in the above example.

It means:

“After receiving a value, wait 500 milliseconds.
If no new value arrives during that time, emit it.
If a new value arrives before 500 milliseconds, cancel the previous wait and start again.”

So the timer is attached to each emission.

debounce() is time-based filtering. It prevents noisy rapid emissions from triggering unnecessary processing.

Why does debounce() reset?

Because debounce is designed to detect silence. It does not care about how many values come.

It only cares about - Has there been a pause long enough?

If not, it keeps postponing emission.

Why This Matters in Stock Analysis

Real scenarios:

  • Stock symbol search

  • Country filtering

  • Market cap range sliders

  • Price filters

  • Dashboard filters

You do not want to recompute analytics for every tiny input change.

You wait for stability.