SNM
SNM

Reputation: 6795

How to return an exception from a method called with .await()

I'm implementing with the new google services coroutines extension functions to return an exception from an asynchronous call

suspend fun saveUserToken(user: User): Resource<Boolean> {
    val result = FirebaseInstanceId.getInstance().instanceId.await()
    user.deviceToken = result.token
    FirebaseFirestore.getInstance().collection("user").document(user.uid).set(user).await()
    return Resource.success(true)
}

Here I do two asynchronous operations, first one retrieves the user device token, and the second one stores that device token + user data into Firestore

Now my question is.

How do I know or return an exception from these two methods if one is throw ?

Since is a Task, the exception should return in a form of the same object, I have read the .await() method to see how it handles the exceptions

public suspend fun <T> Task<T>.await(): T {
    // fast path
    if (isComplete) {
        val e = exception
        return if (e == null) {
            if (isCanceled) {
                throw CancellationException("Task $this was cancelled normally.")
            } else {
                result
            }
        } else {
            throw e
        }
    }

    return suspendCancellableCoroutine { cont ->
        addOnCompleteListener {
            val e = exception
            if (e == null) {
                if (isCanceled) cont.cancel() else cont.resume(result)
            } else {
                cont.resumeWithException(e)
            }
        }
    }
}

Here are two types of exception, one is the task exception from where its called (this is the exception I want to catch in my first code block) and the second is the CancellationException which triggers when the coroutine is cancelled

Upvotes: 3

Views: 1143

Answers (1)

Doug Stevenson
Doug Stevenson

Reputation: 317497

Just use try/catch like you would with any other code:

try {
    val result = FirebaseInstanceId.getInstance().instanceId.await()
    user.deviceToken = result.token
    FirebaseFirestore.getInstance().collection("user").document(user.uid).set(user).await()
    return Resource.success(true)
}
catch (e: Exception) {
    // handle the error here
}

Or you can put the try/catch around the call to saveUserToken. In either case, if a suspend fun inside the try catch yields an error, your catch will trigger.

I suggest reading the documentation on exception handling with Kotlin coroutines.

Upvotes: 3

Related Questions