[ASK] How can I get throw exception as onError/onFailure/onException in ViewModel ?
chanjungkim opened this issue · comments
This is related to this question
In the Repository.
suspend fun reCheckout(
orderData: OrderData
) = flow{
var jwt: String? = null
loginAndRegister(orderData.phoneNumber)
.suspendOnFailure { emit(this) }
.suspendMapSuccess {
val authData = this
jwt = "jwt ${authData.auth.token}"
Client.saveAuth(authData)
cancelOrder(
orderData.orderId!!,
OrderCancelRequestBody("store", "re-checkout")
).getOrThrow()
}
.suspendOnFailure { emit(this) }
.suspendMapSuccess { addMultiCartItem(jwt!!, orderData.multiCartBody!!).getOrThrow() }
.suspendOnFailure { emit(this) }
.suspendMapSuccess { checkOut(orderData.checkoutBody!!).getOrThrow() }
.suspendOnFailure { emit(this) }
.suspendOnSuccess { emit(this) }
}
And
In the ViewModel that calls the Repository.
repository.reCheckout(orderData!!).collectLatest { apiResponse ->
apiResponse.onSuccess {
try {
val checkoutResponse = data as CheckoutResponseBody
orderData!!.updateCheckoutResult(checkoutResponse)
_uiState.value = PaymentUiState.Success(orderData!!)
}catch (e: Exception){
e.printStackTrace()
sendLog(e.stackTraceToString())
}
}.onError {
sendLog("${this.errorBody?.string()}")
}.onException {
sendLog("$exception")
}
}
I am using in this way. And when one of the API calls gets error, it throws because it usesgetOrThrow()
.
public fun <T> ApiResponse<T>.getOrThrow(): T {
when (this) {
is ApiResponse.Success -> return data
is ApiResponse.Failure.Error -> throw RuntimeException(message())
is ApiResponse.Failure.Exception -> throw exception
}
}
But I think that would be nice if I can get the response because checking the status code is important to check the server error.
I thought I could get the exception in the ViewModel. Is there anyway to approach this..?
So, I tried to do like this. But it's not working.
try {
cancelOrder(
orderData.orderId!!,
OrderCancelRequestBody("store", "re-checkout")
).getOrThrow()
}catch (e: Exception){
val result = Response.error(500, e.message?.toResponseBody(null))
emit(ApiResponse.of { result })
}
I also need to dismiss like loading animation or something too.
Hey @chanjungkim, for this check out the example below:
fun sequential() = flow {
disneyService.fetchDisneyPosters().apply { emit(this) }
.suspendMapSuccess {
disneyService.fetchDisneyPosters1().apply { emit(this) }.getOrThrow()
}
.suspendOnSuccess {
disneyService.fetchDisneyPosters2().apply { emit(this) }.getOrThrow()
}
}.catch { emit(ApiResponse.error(it)) }
You can catch the overall exceptions by attaching a catch
extension to your flow:
= flow {
loginAndRegister(orderData.phoneNumber).apply { emit(this) }
.suspendMapSuccess {
val jwt = "jwt ${data.auth.token}"
Client.saveAuth(data)
cancelOrder(
orderData.orderId,
OrderCancelRequestBody("store", "re-checkout")
).apply { emit(this) }.getOrThrow()
}
.suspendMapSuccess { addMultiCartItem(jwt, orderData.cartItems).apply { emit(this) }.getOrThrow() }
.suspendMapSuccess { checkOut(orderData.checkoutBody!!).apply { emit(this) }.getOrThrow() }
.suspendOnSuccess { emit(this) }
}.catch { emit(ApiResponse.error(it)) }