Async/Await é um par de palavras-chave para escrever código assíncrono em estilo síncrono, disponível em Swift desde iOS 13 e em Kotlin com corrotinas. De acordo com Apple Swift Documentation, 2026, Async/Await substitui cadeias de callbacks e GCD, tornando o código assíncrono linear e legível. A palavra-chave async marca uma função como assíncrona, e await suspende sua execução até receber o resultado.
Principais Pontos
Async/Await é uma construção de linguagem que permite escrever código assíncrono de forma tão linear quanto o síncrono. Em Swift, apareceu no iOS 13 / macOS 10.15 junto com o framework Swift Concurrency. Em Kotlin, async/await está disponível através da biblioteca de corrotinas (kotlinx.coroutines) a partir da versão 1.3.
Antes do async/await, o código assíncrono era construído em callbacks, GCD ou RxSwift. Cadeias de callbacks aninhados levavam ao callback hell — um aninhamento profundo que dificulta a leitura e a depuração. Async/Await resolve esse problema permitindo que funções assíncronas “suspensas” nos pontos await e retomem após receber o resultado.
De acordo com o Google (2025), usar async/await em Kotlin reduz o número de linhas de código assíncrono em 40–60% em comparação com a abordagem de callbacks. Em Swift, a adoção do Swift Concurrency atingiu 68% entre os aplicativos publicados em 2025. iOS 16 adicionou suporte ao Swift Concurrency no UIKit, SwiftUI e Foundation, tornando o async/await a ferramenta padrão para todos os novos projetos da Apple.
A principal diferença entre async/await e threads é a suspensão sem bloqueio. Quando uma função encontra await, ela suspende, liberando a thread atual para outras tarefas. Após a conclusão da operação assíncrona, a função retoma na mesma ou em uma thread diferente. Isso é chamado de multitarefa cooperativa.
Uma função async é compilada em uma máquina de estados — um autômato finito que gerencia os estados de execução. No ponto await, o compilador salva o contexto (variáveis locais, endereço de retorno) e entrega o controle ao runtime. Quando o resultado está pronto, o runtime restaura o contexto e continua a execução.
Em Swift, essa máquina de estados é implementada no nível do compilador SIL (Swift Intermediate Language). Em Kotlin, utiliza-se o mecanismo Continuation Passing Style (CPS): cada função suspend aceita um parâmetro Continuation oculto através do qual o resultado é retornado. Ambas as abordagens garantem retomada segura sem vazamentos de memória.
A abordagem de callbacks requer passar um closure que é chamado após a conclusão da operação. Com três requisições sequenciais, você obtém três níveis de aninhamento com tratamento de erros em cada nível. Async/Await transforma essas mesmas três requisições em três linhas sequenciais com um único bloco catch.
GCD (DispatchQueue) resolve o callback hell através de filas seriais e DispatchGroup, mas permanece verboso. Para uma tarefa simples — carregar usuário, depois amigos, depois UI — são necessárias filas, grupos e blocos notify. Async/Await realiza a mesma tarefa com três linhas em uma única função.
| Aspecto | Callback | GCD | Async/Await |
|---|---|---|---|
| Aninhamento | Profundo (pirâmide da perdição) | Médio (grupos+notify) | Linear (plano) |
| Tratamento de erros | Por callback | Manual | Unificado (try/catch) |
| Cancelamento | Manual | Limitado | Task.cancel() |
| Thread safety | Manual | Via fila serial | Via MainActor |
De acordo com a Apple WWDC 2024, Swift Concurrency async/await é a abordagem recomendada para novo código. GCD permanece para integração com bibliotecas C e cenários específicos de baixo nível de manipulação de threads.
Task é a unidade básica de trabalho assíncrono em Swift. Uma Task é criada no contexto de um ator existente ou em uma thread arbitrária. Dentro de uma Task, é possível chamar funções async através de await. TaskGroup permite iniciar várias tarefas filhas em paralelo e coletar seus resultados — um análogo do DispatchGroup turbinado.
Actor é um tipo de referência thread-safe que protege seu estado de condições de corrida. O compilador garante que o acesso às propriedades do ator só é possível através de chamadas async ou dentro do isolamento do ator. Actor substitui a DispatchQueue serial para proteger o estado mutável compartilhado sem bloqueios manuais.
O princípio da Structured Concurrency afirma: cada tarefa assíncrona tem um pai, e o pai não é concluído até que todos os seus filhos sejam concluídos. Se a tarefa A inicia Task { await B() }, então A espera por B. Isso evita vazamentos de tarefas e garante um ciclo de vida previsível.
Em Kotlin, async/await é implementado através de corrotinas — threads leves da linguagem. Uma função é marcada com a palavra-chave suspend (análoga ao async do Swift). Para iniciar, usa-se launch (fire-and-forget) ou async (com resultado). Await é chamado para obter o resultado de async.
Dispatcher determina em qual pool de threads a corrotina executa: Dispatchers.Main para UI, Dispatchers.IO para rede/disco e Dispatchers.Default para tarefas intensivas em CPU. Structured Concurrency é garantida através de CoroutineScope — quando o escopo é cancelado, todas as corrotinas filhas são canceladas.
De acordo com a JetBrains (2025), 97% dos aplicativos Android no Google Play usam kotlinx.coroutines, e 82% deles usam async/await para requisições de rede. As corrotinas se tornaram o padrão de facto para programação assíncrona em Android. Kotlin Multiplatform também suporta corrotinas, permitindo usar código assíncrono compartilhado em Android, iOS e no lado do servidor.
Vejamos dois exemplos para cada linguagem: carregamento sequencial de dados e requisições paralelas com TaskGroup ou async/await.
await suspende a execução até receber os dados do usuário, depois até receber os amigos. Sem closures aninhadas.
func loadProfile() async throws -> Profile {
let user = try await api.fetchUser()
let friends = try await api.fetchFriends(for: user.id)
return Profile(user: user, friends: friends)
}
TaskGroup inicia tarefas em paralelo e coleta os resultados em um array. A ordem dos resultados pode não corresponder à ordem de início.
func loadParallel() async throws -> [String] {
await withThrowingTaskGroup(of: String.self) { group in
group.addTask { try await api.fetchName() }
group.addTask { try await api.fetchEmail() }
group.addTask { try await api.fetchAvatar() }
var results = [String]()
for try await value in group { results.append(value) }
return results
}
}
Funções suspend podem chamar outras funções suspend. Análogo ao Swift: chamadas sequenciais.
suspend fun loadProfile(): Profile {
val user = api.fetchUser()
val friends = api.fetchFriends(user.id)
return Profile(user, friends)
}
Em Kotlin, o paralelismo é alcançado através de coroutineScope com async para cada requisição.
suspend fun loadParallel(): List<String> = coroutineScope {
val name = async { api.fetchName() }
val email = async { api.fetchEmail() }
val avatar = async { api.fetchAvatar() }
listOf(name.await(), email.await(), avatar.await())
}
Task { } esquecida — uma função async não pode ser chamada de um contexto síncrono sem ser envolvida em uma Task. Em Swift, isso gera erro de compilação. Em Kotlin, requer inicialização através de lifecycleScope ou viewModelScope. Tentar chamar uma função suspend de uma função normal não compilará.
Nem toda função precisa ser assíncrona. Tarefas intensivas em CPU sem E/S não se beneficiam de async — é melhor executá-las em DispatchQueue com QoS .userInitiated. Async/Await é otimizado para operações vinculadas a E/S: rede, disco, espera.
Usar .result na thread principal (espera síncrona pelo resultado de uma função async) leva ao bloqueio. Em Swift, Task.synchronousWait não é recomendado pela Apple. Em Kotlin, runBlocking na thread principal é um antipadrão — use lifecycleScope.
Se uma Task não for armazenada em uma propriedade da classe, ao sair do contexto ela é cancelada. Em Swift, Task tem escopo — seu ciclo de vida está vinculado ao contexto criador. Armazene a Task em uma propriedade se precisar de uma operação de longa duração.
Perguntas Frequentes
Async/Await é uma construção de linguagem que não requer criar filas. DispatchQueue é uma API de sistema para gerenciar threads. Async/await compila em uma máquina de estados no nível da linguagem, GCD — em syscalls no nível do SO.
Não — await suspende a função mas libera a thread para outras tarefas. Após a conclusão da operação, a função retoma em qualquer thread disponível do pool.
Sim — através de Task.cancel() em Swift ou Job.cancel() em Kotlin. O cancelamento se propaga para todas as tarefas filhas de acordo com a Structured Concurrency. O código verifica a flag de cancelamento através de Task.isCancelled ou ensureActive().
MainActor é um ator cujas propriedades e métodos sempre executam na thread principal. Marcando uma função com @MainActor, você garante que as atualizações de UI ocorrem na thread correta, substituindo DispatchQueue.main.async.
Async/Await está disponível em Swift (iOS 13+), Kotlin (via kotlinx.coroutines), Dart (Flutter), JavaScript/TypeScript, Python, C#, Rust e Go (via goroutines com açúcar sintático).
Resumo
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.
Leia também