@@ -317,29 +317,33 @@ public fun <T> Flow<T>.stateIn(
317
317
* with multiple downstream subscribers. See the [StateFlow] documentation for the general concepts of state flows.
318
318
*
319
319
* @param scope the coroutine scope in which sharing is started.
320
+ * @throws NoSuchElementException if the upstream flow does not emit any value.
320
321
*/
321
322
public suspend fun <T > Flow<T>.stateIn (scope : CoroutineScope ): StateFlow <T > {
322
323
val config = configureSharing(1 )
323
- val result = CompletableDeferred <StateFlow <T >>( )
324
+ val result = CompletableDeferred <Result < StateFlow <T >>>(scope.coroutineContext[ Job ] )
324
325
scope.launchSharingDeferred(config.context, config.upstream, result)
325
- return result.await()
326
+ return result.await().getOrThrow()
326
327
}
327
328
328
329
private fun <T > CoroutineScope.launchSharingDeferred (
329
330
context : CoroutineContext ,
330
331
upstream : Flow <T >,
331
- result : CompletableDeferred <StateFlow <T >>
332
+ result : CompletableDeferred <Result < StateFlow <T >>>,
332
333
) {
333
334
launch(context) {
334
335
try {
335
336
var state: MutableStateFlow <T >? = null
336
337
upstream.collect { value ->
337
338
state?.let { it.value = value } ? : run {
338
339
state = MutableStateFlow (value).also {
339
- result.complete(ReadonlyStateFlow (it, coroutineContext.job))
340
+ result.complete(Result .success( ReadonlyStateFlow (it, coroutineContext.job) ))
340
341
}
341
342
}
342
343
}
344
+ if (state == null ) {
345
+ result.complete(Result .failure(NoSuchElementException (" Flow is empty" )))
346
+ }
343
347
} catch (e: Throwable ) {
344
348
// Notify the waiter that the flow has failed
345
349
result.completeExceptionally(e)
0 commit comments