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
- SupervisorJob vs Job: isolamento de falhas
- CoroutineExceptionHandler: manipulador global de exceções não capturadas
- Propagação de exceções em async/await
- Projetando arquiteturas resilientes de corrotinas