Hi all :kodee-greetings: , I have a coroutine that...
# coroutines
a
Hi all kodee greetings , I have a coroutine that has few children coroutines and suspend method calls. How to rethrow an exception thrown by one of the suspending method calls? Code example in 🧵
Copy code
fun initViewModel(): Job {
  return coroutineScope.launch {
    coroutineScope.launch { // Observes data 1 continuously
      observeData1().collectLatest {
        refreshUiState()
      }
    }
    coroutineScope.launch { // Observes data 2 continuously
      observeData2().collectLatest {
        refreshUiState()
      }
    }
    fetchData1() // Can throw an exception like "IllegalArgumentException"
  }
}
Currently, when
fetchData1()
throws an exception,
initViewModel()
throws
JobCancellationException
instead of the exception thrown by
fetchData1()
. How to make
initViewModel()
throw the actual exception thrown by
fetchData1()
?
s
Is
coroutineScope
your custom scope that you created?
BTW you for
observeData1()
and
observeData2()
you can omit
coroutinseScope
and just use
Copy code
coroutineScope.launch {
  launch {
    // 1
  }
  launch {
    // 2
  }
}
I believe
☝🏻 1
d
we can run
fetchData1()
in
async
and
await
something like this
Copy code
fun initViewModel(): Job {
    return coroutineScope.launch {
        val job1 = launch { observeData1().collectLatest { refreshUiState() } }
        val job2 = launch { observeData2().collectLatest { refreshUiState() } }

        val deferred = async { fetchData1() }
        deferred.await() // exception propagates here
    }
}
a
Hi @Sergey Dmitriev,
coroutineScope
is injected and used like this.
Copy code
CoroutineScope(
  dispatcherProvider.mainImmediate + SupervisorJob(),
)
Copy code
internal class EditAccountScreenViewModel(
    private val coroutineScope: CoroutineScope,
    // 
) : ViewModel(
    viewModelScope = coroutineScope,
)
Can ignore the observing data part it is just a sample example. The main question I have is how to rethrow exception from fetchData.
Hi @Deeksha Agrawal,
Copy code
val deferred = async { fetchData1() }
deferred.await() // exception propagates here
is same as
Copy code
val deferred = async { fetchData1() }.await() // exception propagates here
So, the async is called followed immediately by
await()
.
fetchData1()
is a suspending method and it seems equivalent to my original code. I tried this as well to see if it makes any difference in error handling, and I observed that it doesn’t.
d
For this scenario either we can wrap siblings in supervisorScope or can something try like this:
Copy code
runCatching {
            fetchData1()
        }.onFailure { e ->
            
        }