Async/Await: essência, funções async e trabalho com await

Autor: IT Sectr Publicado: 2026-03-16 Tempo de leitura: 8 min

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 é açúcar sintático para código assíncrono sem callbacks aninhados
  • async marca uma função como assíncrona e suspensível
  • await suspende a execução da função até a conclusão da operação assíncrona
  • Task em Swift cria uma nova unidade de trabalho assíncrona com contexto
  • Structured Concurrency garante que todas as tarefas filhas sejam concluídas antes da pai

O que é Async/Await e programação assíncrona

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.

Princípio de funcionamento: funções suspensíveis

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.

Como o Async/Await funciona: suspensão e retomada

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.

  • Swift — o compilador traduz a função async para SIL com um runAsync coroutine frame
  • Kotlin — cada função suspend recebe um Continuation e delega a execução ao dispatcher
  • Ambas as linguagens — liberam a thread no await, sem bloqueá-la durante a espera
  • Exceções — são propagadas através de mecanismos padrão (throws / try-catch)

Async/Await vs Callbacks e GCD: comparação de abordagens

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.

AspectoCallbackGCDAsync/Await
AninhamentoProfundo (pirâmide da perdição)Médio (grupos+notify)Linear (plano)
Tratamento de errosPor callbackManualUnificado (try/catch)
CancelamentoManualLimitadoTask.cancel()
Thread safetyManualVia fila serialVia 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.

Swift Concurrency: Task, TaskGroup e Actor

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.

Structured Concurrency

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.

Async/Await em Kotlin com corrotinas

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.

Exemplos de código com Async/Await em Swift e Kotlin

Vejamos dois exemplos para cada linguagem: carregamento sequencial de dados e requisições paralelas com TaskGroup ou async/await.

Swift: Chamadas async sequenciais

await suspende a execução até receber os dados do usuário, depois até receber os amigos. Sem closures aninhadas.

swift
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)
}

Swift: Requisições paralelas com TaskGroup

TaskGroup inicia tarefas em paralelo e coleta os resultados em um array. A ordem dos resultados pode não corresponder à ordem de início.

swift
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
    }
}

Kotlin: Chamada sequencial com async/await

Funções suspend podem chamar outras funções suspend. Análogo ao Swift: chamadas sequenciais.

kotlin
suspend fun loadProfile(): Profile {
    val user = api.fetchUser()
    val friends = api.fetchFriends(user.id)
    return Profile(user, friends)
}

Kotlin: Requisições paralelas com async/await

Em Kotlin, o paralelismo é alcançado através de coroutineScope com async para cada requisição.

kotlin
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())
}

Erros comuns e limitações do Async/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á.

Uso excessivo de async sem necessidade

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.

Bloqueio da thread principal através de .result

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.

Vazamento de Task ao cancelar

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

Como o async/await difere do DispatchQueue?

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.

O await bloqueia a thread?

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.

Pode-se cancelar uma tarefa async?

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().

O que é MainActor em Swift?

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.

Em quais linguagens existe async/await?

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

  • Async/Await é uma construção de linguagem para código assíncrono linear sem callback hell
  • Swift Concurrency fornece Task, TaskGroup, Actor e Structured Concurrency
  • Corrotinas de Kotlin usam funções suspend, Dispatchers e escopos de corrotina
  • Suspensão sem bloqueio é a principal diferença do async/await em relação a threads e filas
  • Structured Concurrency garante que todas as tarefas filhas sejam concluídas antes da pai
  • Async/Await vs GCD — o primeiro é preferível para código novo, o segundo para legado e baixo nível
  • MainActor em Swift e Dispatchers.Main em Kotlin protegem a thread de UI de operações em segundo plano

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