JakeWharton / retrofit2-kotlin-coroutines-adapter

A Retrofit 2 adapter for Kotlin coroutine's Deferred type.
Apache License 2.0
1.97k stars 128 forks source link

Error handling with coroutines #16

Closed Ahmed-Adel-Ismail closed 6 years ago

Ahmed-Adel-Ismail commented 6 years ago

The documentation does not tell how to handle failed responses when expecting a Deferred object ?

bradynpoulsen commented 6 years ago

This would be resolved when you join() or await() on the Deferred in your coroutine.

For example, let's say that the following call raised a MissingParameterException during conversion

interface UserService {
    @GET("/user/{id}")
    fun find(@Path("id") id: Int): Deferred<User>
}

fun foo() {
    val retrofit = Retrofit.Builder().addCallAdapterFactory(...).build()
    val service = retrofit.create(UserService::class.java)

    val syncCurrentUserJob = launch(MySyncContext) {
        val deferredUser = service.find(currentUserId)

        val user = try {
            deferredUser.await()
        } catch (missingParam: MissingParameterException) {
            // our conversion failed, wrap it in an exception specific to syncing
            throw SyncFailedException("failed to sync current user: $currentUserId", cause = missingParam)
        }

        userRepo.update(user)
    }

    // our job caught the MissingParameterException and wrapped it in SyncFailedException
    // calling `.join()` will raise any exception that occurred during the Job (in our case, the wrapping SyncFailedException
    runBlocking { syncCurrentUserJob.join() }
}

Documentation for Deferred<out T>.await()

Awaits for completion of this value without blocking a thread and resumes when deferred computation is complete,
returning the resulting value or throwing the corresponding exception if the deferred had completed exceptionally.
Ahmed-Adel-Ismail commented 6 years ago

Thanks