Mark
05/29/2024, 3:47 AMMark
05/29/2024, 4:16 AMcombine
where you don’t want an input flow
to potentially forever hold up the combine
flow
Mark
05/29/2024, 4:34 AMfun <T> Flow<T>.emitInitialValueOnTimeout(
timeoutMillis: Long,
initialValue: T
): Flow<T> = flow {
try {
withTimeout(timeoutMillis) {
emit(this@emitInitialValueOnTimeout.first())
}
emitAll(this@emitInitialValueOnTimeout.drop(1))
} catch (e: TimeoutCancellationException) {
emit(initialValue)
emitAll(this@emitInitialValueOnTimeout)
}
}
https://pl.kotl.in/IpOwN6OK3
But the first(), drop(1) doesn’t look safe to meZach Klippenstein (he/him) [MOD]
05/29/2024, 4:45 AMcombine
?Zach Klippenstein (he/him) [MOD]
05/29/2024, 4:46 AMMark
05/29/2024, 4:50 AMMark
05/29/2024, 4:50 AMSharedFlow
first?Zach Klippenstein (he/him) [MOD]
05/29/2024, 4:59 AMfun <T> Flow<T>.emitInitialAfterTimeout(
timeoutMillis: Long,
initialValue: T
): Flow<T> = channelFlow {
var fallbackJob: Job? = launch {
delay(timeoutMillis)
send(initialValue)
}
collect {
fallbackJob?.let {
it.cancelAndJoin()
fallbackJob = null
}
send(it)
}
}
Mark
05/29/2024, 5:16 AMMark
05/29/2024, 5:31 AMfun <T> Flow<T>.emitInitialNullOnTimeout(
timeoutMillis: Long,
): Flow<T?>
but is there any way to specify a type R
as T
or T?
so that can return Flow<R>
?
fun <T, R: T or T?> Flow<T>.emitInitialValueOnTimeout(
timeoutMillis: Long,
initialValue: R,
): Flow<R>
Mark
05/29/2024, 3:41 PMfun <T> Flow<T>.emitInitialValueIfBeforeFirst(
initialValue: suspend () -> T,
): Flow<T> = channelFlow {
var initialValueJob: Job? = launch {
val value = initialValue()
logi("emitting initialValue: $value because first value not yet emitted")
send(value)
}
collect { item ->
initialValueJob?.let { job ->
job.cancelAndJoin()
initialValueJob = null
}
send(item)
}
}
which means can also use it for the earlier extension fun:
fun <T> Flow<T>.emitInitialValueOnTimeout(
timeoutMillis: Long,
initialValue: T,
): Flow<T> = emitInitialValueIfBeforeFirst {
delay(timeoutMillis)
initialValue
}
reline
05/29/2024, 7:02 PMMark
05/30/2024, 3:40 AMemitInitialAfterTimeout()
directly.