0Pricing
Kotlin Academy · Aula

Propagação de exceções em async/await

Entenda como as exceções de async se propagam e quando usar try-await.

Propagação de exceções em async/await é uma aula grátis de Kotlin Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Kotlin Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Kotlin Academy inclui 4 aulas no total.

Execução Assíncrona Armazena Exceções

Ao contrário de launch, async armazena a exceção no Deferred retornado. Ela só é lançada novamente quando você chama await().

import kotlinx.coroutines.*
fun main() = runBlocking {
    val deferred = async {
        throw RuntimeException("async error")
    }
    try {
        deferred.await()  // exception rethrown here
    } catch (e: RuntimeException) {
        println("Caught: ${e.message}")
    }
}

Exceção sem await()

Se você nunca chamar await(), a exceção será silenciosamente descartada com um pai Job regular. Prefira supervisorScope + aguarde sempre.

import kotlinx.coroutines.*
fun main() = runBlocking {
    // Exception stored in deferred, never retrieved:
    val d = async { throw RuntimeException("lost exception") }
    delay(100)  // d has failed — exception never surfaced
    println("d.isCancelled: ${d.isCancelled}")
}

Execução Assíncrona em coroutineScope

Em um coroutineScope regular, se um filho assíncrono lançar uma exceção que se propague (sem ser capturada), ele cancelará o escopo e todos os irmãos.

import kotlinx.coroutines.*
fun main() = runBlocking {
    try {
        coroutineScope {
            val a = async { "A" }
            val b = async { throw RuntimeException("B failed") }
            println(a.await())
            println(b.await())  // propagates, cancels scope
        }
    } catch (e: RuntimeException) {
        println("Scope failed: ${e.message}")
    }
}

Execução Assíncrona em supervisorScope

Em supervisorScope, as exceções de async NÃO se propagam para os irmãos. Cada await()` must be wrapped individually.

import kotlinx.coroutines.*
fun main() = runBlocking {
    supervisorScope {
        val a = async { "A" }
        val b = async { throw RuntimeException("B failed") }
        println(a.await())
        try { println(b.await()) }
        catch (e: RuntimeException) { println("b failed: ${e.message}") }
    }
}

awaitAll para Várias Execuções Assíncronas

awaitAll(d1, d2, d3) aguarda todas as instâncias adiadas. Se alguma falhar, ele lança uma exceção imediatamente e cancela as demais.

import kotlinx.coroutines.*
fun main() = runBlocking {
    try {
        val results = awaitAll(
            async { "result1" },
            async { throw RuntimeException("task 2 failed") },
            async { "result3" }
        )
        println(results)
    } catch (e: Exception) {
        println("awaitAll failed: ${e.message}")
    }
}

runCatching com Execução Assíncrona

Envolva cada await() em runCatching para reunir resultados e erros sem interromper o processamento no primeiro erro.

import kotlinx.coroutines.*
fun main() = runBlocking {
    supervisorScope {
        val deferreds = listOf(
            async { "A" },
            async { throw RuntimeException("B") },
            async { "C" }
        )
        val results = deferreds.map { runCatching { it.await() } }
        results.forEach { println(it) }
    }
}

Tarefas Paralelas com Acúmulo de Erros

Reúna todas as falhas das tarefas assíncronas paralelas e relate-as em conjunto, em vez de falhar imediatamente.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val tasks = listOf("a", "b", "c")
    val results = supervisorScope {
        tasks.map { t ->
            async {
                if (t == "b") throw RuntimeException("b failed")
                t.uppercase()
            }
        }.map { runCatching { it.await() } }
    }
    val errors = results.filter { it.isFailure }
    val successes = results.mapNotNull { it.getOrNull() }
    println("Success: $successes, Errors: ${errors.size}")
}

Preservação do Tipo da Exceção

As exceções lançadas dentro de async preservam seu tipo. Capture o tipo específico da exceção em await() para tratar o erro com precisão.

import kotlinx.coroutines.*
class NetworkException(msg: String) : RuntimeException(msg)
fun main() = runBlocking {
    val d = async { throw NetworkException("timeout") }
    try {
        d.await()
    } catch (e: NetworkException) {
        println("Network error: ${e.message}")
    } catch (e: Exception) {
        println("Other error: ${e.message}")
    }
}

Deferred.getCompleted() para Verificação sem Suspensão

Depois de join(), use getCompleted() para recuperar o resultado de forma síncrona. Ele lança uma exceção se a execução adiada tiver falhado.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val d = async { 42 }
    d.join()  // wait without caring about result
    try {
        val result = d.getCompleted()  // synchronous — no suspend
        println("Result: $result")
    } catch (e: Exception) {
        println("Failed: ${e.message}")
    }
}

Concorrência Estruturada e Execução Assíncrona

Na concorrência estruturada, uma execução assíncrona adiada está sempre vinculada ao escopo pai. Quando o escopo é cancelado, a execução adiada também é cancelada — não há tarefas órfãs.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val scope = CoroutineScope(SupervisorJob())
    val d = scope.async {
        delay(1000)
        "result"
    }
    scope.cancel()  // cancels d too
    try { d.await() }
    catch (e: CancellationException) { println("Cancelled as expected") }
}

Boa Prática: Aguarde Sempre

Sempre use await() para aguardar cada execução assíncrona adiada, mesmo que você não precise do resultado. Isso revela as exceções e evita falhas silenciosas.

import kotlinx.coroutines.*
fun main() = runBlocking {
    supervisorScope {
        val d = async {
            // do background work
            "done"
        }
        // Always await:
        val result = runCatching { d.await() }
        println(result)
    }
}

Verificação Rápida

Quando a exceção de um bloco async { throw ... } se torna evidente?

Recapitulação

async armazena exceções em Deferred; elas aparecem em await(). Em coroutineScope, a propagação cancela os irmãos. Em supervisorScope, cada await precisa tratar sua própria falha. Aguarde sempre cada execução adiada.

Perguntas Frequentes

A aula “Propagação de exceções em async/await” é grátis?

Sim — o texto completo de “Propagação de exceções em async/await” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Kotlin Academy, atualize para CoddyKit PRO. O curso de Kotlin Academy inclui 4 aulas no total.

O que vou aprender em “Propagação de exceções em async/await”?

Entenda como as exceções de async se propagam e quando usar try-await. Você pratica Kotlin Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Kotlin Academy?

Nenhuma experiência prévia é necessária. Kotlin Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.

Quanto tempo leva a aula “Propagação de exceções em async/await”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Kotlin Academy?

Sim. Cada aula de Kotlin Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. SupervisorJob vs Job: isolamento de falhas
  2. CoroutineExceptionHandler: manipulador global de exceções não capturadas
  3. Propagação de exceções em async/await
  4. Projetando arquiteturas resilientes de corrotinas
← Voltar para Kotlin Academy