Is there a way to wait for an element from a flow ...
# coroutines
b
Is there a way to wait for an element from a flow with some timeout? Like to emit either 1) whatever is sent on the wrapped flow or 2) something else if the wrapped flow doesn't produce an element within some time period?
b
I believe onStart+transformLatest+delay should do the trick, and even may look nice 🙂 (but it will use channel under the hood anyway)
Something like: flow.onStart { emit(null) } .transformLatest { if (it != null) emit(it) delay(500) emit(42) } (didn't test it)
b
Oh interesting! That's a good idea
I found this post (https://github.com/Kotlin/kotlinx.coroutines/issues/1183) and have been playing with this:
Copy code
fun <T> Flow<T>.withDefaultAfterTimeout(default: T, timeoutMs: Long): Flow<T> = flow {
    coroutineScope { // delimit a scope in which flow is running
        val channel = produceIn(this) // run flow in the scope
        while (isActive) {
            val result = withTimeoutOrNull(timeoutMs) {
                select<T> {
                    channel.onReceive { it }
                }
            } ?: default
            emit(result)
        }
    }
}
Why is the
flow.onStart { emit(null) }
needed?
b
Otherwise there will be no timeout before first item appears
b
ah
Ah, one issue with this method is that I lose elements if they come too close together Ignore me, I just didn't set the replay value on the underlying flow.