async: o que é, Deferred e corrotinas paralelas como funcionam

Autor: IT Sectr Publicado: 2026-06-22 Tempo de leitura: 8 min

async — é um Construtor de Corrotinas em Kotlin que inicia uma corrotina e retorna um objeto Deferred<T> para obter o resultado de uma operação assíncrona. async permite executar várias tarefas em paralelo e agregar seus resultados através de await(). De acordo com o guia JetBrains, 2024, async é a forma preferida de organizar cálculos paralelos em corrotinas.

Principais Pontos

  • async — um construtor de corrotinas que retorna Deferred<T> com o resultado de uma operação assíncrona
  • Deferred — uma promessa assíncrona, herdeira de Job, com o método await() para obter o resultado
  • async permite executar tarefas independentes em paralelo, reduzindo o tempo total
  • await() — uma função suspend que suspende a corrotina até obter o resultado sem bloquear
  • Concorrência estruturada com async garante o cancelamento de todas as tarefas paralelas em caso de erro

O que é async em Kotlin Coroutines?

async — é uma função de extensão do CoroutineScope que cria uma corrotina retornando um resultado. Ao contrário do launch, async retorna Deferred<T> — um objeto que representa um valor futuro. Uma corrotina iniciada via async executa concorrentemente com outras corrotinas, permitindo paralelizar cálculos.

async é usado quando o resultado de uma operação assíncrona é necessário para processamento posterior: carregar dados de várias fontes, processamento em lote de coleções, requisições paralelas a várias APIs. Deferred é criado imediatamente, e o resultado fica disponível após a conclusão da corrotina.

kotlin
import kotlinx.coroutines.*

suspend fun String.delayedValue(): String {
    delay(1000L)
    return this
}

fun main() = runBlocking {
    val deferred: Deferred<String> = async { "Hello".delayedValue() }
    println(deferred.await())
}

Sintaxe do async e Deferred

A assinatura do async é semelhante ao launch: os mesmos parâmetros CoroutineContext, CoroutineStart e um bloco suspend. A diferença está no tipo de retorno — Deferred<T> em vez de Job, onde T é o tipo de resultado retornado pela última expressão do bloco.

kotlin
public fun <T> CoroutineScope.async(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> T
): Deferred<T>

Deferred<T> — uma interface que herda Job e adiciona os métodos await(), getCompleted(), getCompletionExceptionOrNull(). await() é uma função suspend e só pode ser chamada dentro de uma corrotina ou outra função suspend. getCompleted() é um método não bloqueante que lança uma exceção se a corrotina ainda não foi concluída.

Tarefas paralelas com async

A principal vantagem do async é a capacidade de executar tarefas em paralelo. Em vez de esperar cada operação sequencialmente (tempo total = soma dos tempos), async inicia corrotinas simultaneamente, reduzindo o tempo total para a duração da operação mais longa.

Carregamento paralelo de dados

Um cenário típico — carregar o perfil do usuário, suas configurações e histórico de pedidos com três requisições async paralelas. Após a conclusão das três, os resultados são combinados em um único modelo de dados.

kotlin
suspend fun loadUserDashboard(userId: String): Dashboard = coroutineScope {
    val profile = async { api.getProfile(userId) }
    val settings = async { api.getSettings(userId) }
    val orders = async { api.getRecentOrders(userId) }

    Dashboard(
        profile = profile.await(),
        settings = settings.await(),
        orders = orders.await()
    )
}

A função coroutineScope inicia corrotinas filhas e aguarda sua conclusão antes de retornar o resultado. Todo o bloco executa em paralelo, não sequencialmente.

Tratamento de resultados Deferred

Deferred suporta vários métodos para trabalhar com o resultado. Além de await(), há métodos para verificar o status, obter um valor concluído e agregar vários Deferreds através das funções utilitárias do Kotlin Coroutines.

MétodoDescriçãoSuspend?
await()Suspende a corrotina até obter o resultadoSim
getCompleted()Retorna o resultado se a corrotina foi concluída (senão Exception)Não
getCompletionExceptionOrNull()Retorna a exceção em caso de erro ou nullNão
isCompletedVerifica se a corrotina foi concluídaNão

Para agregar uma lista de Deferreds, usa-se awaitAll() — uma função que suspende a execução até que todos os Deferreds na coleção sejam concluídos. Se pelo menos um concluiu com erro, awaitAll() lança a exceção.

kotlin
suspend fun <T> loadAll(requests: List<suspend () -> T>): List<T> {
    return coroutineScope {
        val deferreds = requests.map { async { it() } }
        deferreds.awaitAll()
    }
}

Diferenças entre async e launch

A escolha entre async e launch depende se o resultado da corrotina é necessário. launch retorna Job e é adequado para operações fire-and-forget, async retorna Deferred e é usado para tarefas que retornam dados. Em termos de sintaxe e parâmetros, os construtores são idênticos.

  • launch → Job (sem resultado), async → Deferred<T> (resultado T)
  • launch — tarefas fire-and-forget (logging, cache, envio de análises)
  • async — cálculos paralelos (carregamento de várias APIs, processamento em lote)
  • Ambos suportam concorrência estruturada e parâmetros CoroutineStart
  • await() está disponível apenas para Deferred, launch não fornece resultado

Regra importante: nunca use async para fire-and-forget. Se o resultado da corrotina não for necessário, use launch. async cria sobrecarga ao criar Deferred, o que não se justifica nesses cenários.

Exemplos de async no desenvolvimento mobile

No Android, async é usado para operações paralelas dentro de ViewModel e UseCases. Cenários típicos: carregar perfil e feed de notícias simultaneamente, obter clima de vários serviços meteorológicos, sincronização em lote de dados com o servidor.

kotlin
class HomeViewModel : ViewModel() {
    fun loadHomeScreen() {
        viewModelScope.launch {
            val userData = async(Dispatchers.IO) { repository.getUserData() }
            val newsFeed = async(Dispatchers.IO) { repository.getNewsFeed() }
            val notifications = async(Dispatchers.IO) { repository.getNotifications() }

            val state = HomeState(
                user = userData.await(),
                news = newsFeed.await(),
                unread = notifications.await()
            )
            _uiState.update { state }
        }
    }
}

É recomendado envolver um grupo de async em coroutineScope ou supervisorScope para isolamento de erros. supervisorScope permite que as demais corrotinas async continuem mesmo se uma falhar — útil para operações não críticas.

Perguntas Frequentes

Pode-se usar async sem await?

Pode, mas é inútil. async sem await() inicia uma corrotina mas seu resultado é perdido. Se o resultado não for necessário, use launch — ele não cria Deferred e é mais eficiente em memória e desempenho.

Como o async lida com exceções?

Uma exceção dentro de async é armazenada em Deferred. Chamar await() lança essa exceção. Para verificar sem lançar, use getCompletionExceptionOrNull(). Ao usar coroutineScope, um erro cancela todas as corrotinas filhas.

O que é awaitAll em Kotlin Coroutines?

awaitAll() — uma função de extensão para Iterable<Deferred<T>> que suspende a corrotina até que todos os Deferreds sejam concluídos. Retorna uma lista de resultados. Se pelo menos um Deferred falhar, lança a exceção e cancela os restantes.

Como async difere de GlobalScope.async?

Sim. async é uma função de extensão do CoroutineScope vinculada ao escopo. GlobalScope.async cria uma corrotina sem vinculação ao ciclo de vida — pode executar indefinidamente. GlobalScope não é recomendado no Android devido ao risco de vazamentos.

Quantas corrotinas async podem ser iniciadas para requisições paralelas?

O número é ditado pelo dispatcher: Dispatchers.IO suporta até 64 threads simultâneos, Dispatchers.Default — até o número de núcleos de CPU. Para operações em massa, use paralelismo limitado via Semaphore ou mapNotNull com awaitAll.

Resumo

  • async — um construtor de corrotinas que retorna Deferred<T> para obtenção assíncrona de resultados
  • Deferred herda Job e adiciona os métodos await(), getCompleted(), getCompletionExceptionOrNull()
  • Execução paralela com async reduz o tempo total à duração da operação mais longa
  • awaitAll() — uma utilidade para aguardar todos os Deferreds em uma coleção
  • coroutineScope — envoltório recomendado para um grupo de async com garantia de cancelamento
  • Não use async para fire-and-forget — use launch em vez disso
  • No Android, async é usado para carregamento paralelo em ViewModel com viewModelScope

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também