Future/Promise — o que é, computações assíncronas e programação

Autor: IT Sectr Publicado: 2026-03-17 Tempo de leitura: 9 min

Future/Promise é um padrão de programação assíncrona que representa um contêiner para o resultado de uma operação ainda não concluída. De acordo com Dart Documentation, 2025, Future é um resultado somente leitura de computações diferidas, Promise é um contrato somente escrita que preenche este resultado. Future é usado em Dart, Java, Scala e C++ para cadeias then/catch.

Pontos principais

  • Future — um contêiner somente leitura para um resultado assíncrono disponível no futuro
  • Promise — um placeholder somente escrita que aceita o resultado e o passa para o Future
  • Cadeias then — processamento sequencial de operações assíncronas sem callbacks aninhados
  • Future em Dart — a base de async/await e das bibliotecas dio, http, shelf
  • Future/Promise — uma alternativa ao padrão callback e a base para a sintaxe async/await

O que é Future/Promise?

Future/Promise é um par de objetos interconectados que dividem um resultado assíncrono em dois papéis. Promise pode escrever o resultado (resolve) ou um erro (reject). Future só pode lê-lo — através de callbacks (then, catchError) ou via await. Esta separação garante que o consumidor não possa alterar o resultado, apenas usá-lo.

Future em Dart

A linguagem Dart usa Future como seu principal mecanismo assíncrono. Future<T> é um contrato para receber um valor do tipo T no futuro. Um Future pode estar em um de três estados: unresolved (operação em andamento), resolved with value (concluído com sucesso) ou resolved with error (concluído com erro). Uma vez que transita para um estado resolved, o Future nunca muda.

Promise em JavaScript

Promise em JavaScript é análogo ao Future do Dart, mas com uma API mais rica. Promise recebe um executor — uma função com parâmetros resolve e reject. Os métodos estáticos Promise.all, Promise.race, Promise.allSettled permitem combinar múltiplas promessas. Aplicações modernas usam a sintaxe async/await sobre Promise.

Como o Future funciona

Future funciona com base em um event loop — um ciclo de eventos que processa operações assíncronas sem bloquear a thread principal. Quando uma função assíncrona é chamada (por exemplo, http.get), ela retorna imediatamente um Future. A requisição real é executada em segundo plano, enquanto o event loop continua processando outros eventos. Após a conclusão da operação, o Future transita para o estado resolved e then é chamado.

Event loop é o mecanismo chave sobre o qual Dart e JavaScript são construídos. O event loop mantém duas filas: a fila de microtarefas (tarefas curtas, executadas antes do próximo evento) e a fila de eventos (eventos IO, temporizadores). Future.then coloca um callback na fila de microtarefas, Future.microtask — execução prioritária antes do próximo frame.

Cadeias de then() permitem processar sequencialmente os resultados de operações assíncronas sem callback hell. Cada then() recebe o resultado do passo anterior e retorna um novo Future. catchError() no final da cadeia trata qualquer erro que ocorreu em qualquer passo. Isso torna o código assíncrono linear e legível.

CompletableFuture em Java

Em Java, CompletableFuture estende o conceito Future/Promise. O método supplyAsync() lança uma tarefa assíncrona em ForkJoinPool.commonPool(). thenApply() transforma o resultado, thenCompose() desempacota um CompletableFuture aninhado. exceptionally() trata um erro retornando um valor padrão. allOf() e anyOf() funcionam como Promise.all e Promise.race em JavaScript. CompletableFuture suporta conclusão manual via complete() e completeExceptionally() — isto é análogo a Promise resolve/reject.

Promise e o contrato de assincronia

Promise é um contrato com um de três estados: pending (pendente), fulfilled (cumprido) ou rejected (rejeitado). Uma vez que transita para fulfilled ou rejected, o Promise nunca muda — isto garante a imutabilidade do resultado para todos os consumidores. O método .then() é chamado assincronamente após transitar para qualquer estado concluído.

Promise.all espera que todas as promessas passadas sejam concluídas e retorna um array de resultados na mesma ordem. Se uma promessa falha com um erro — todo Promise.all transita para rejected. Promise.race retorna o resultado da primeira promessa concluída (sucesso ou erro). Promise.allSettled espera todas as promessas independentemente de erros — retorna o status de cada uma.

Chaining (encadeamento) é a vantagem chave do Promise sobre callbacks. Cada .then() retorna um novo Promise, permitindo cadeias de comprimento arbitrário. Um erro em qualquer elo da cadeia propaga para o .catch() mais próximo. O método finally() executa código após a conclusão da cadeia independentemente do resultado — para limpeza de recursos.

Exemplos de código Future (Dart)

O primeiro exemplo — criar um Future através de uma função async e tratá-lo com then/catchError:

dart
Future<String> fetchData() async {
    await Future.delayed(Duration(seconds: 1))
    return "Dados carregados"
}

fetchData()
    .then((result) => print(result))
    .catchError((error) => print("Erro: $error"))

O segundo exemplo — combinar múltiplos Futures com Future.wait:

dart
Future<List<String>> loadAll() async {
    final futures = [
        fetchFromApi("/users"),
        fetchFromApi("/posts"),
        fetchFromApi("/comments")
    ]
    final results = await Future.wait(futures)
    return results
}

O terceiro exemplo — Promise em JavaScript com criação manual e uma cadeia then:

js
const promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve("Concluído")
    }, 1000)
})

promise
    .then(value => console.log(value))
    .catch(err => console.error(err))

Future vs outros padrões assíncronos

Future/Promise difere do estilo callback por retornar um objeto contrato em vez de aceitar uma função callback como argumento. O estilo callback leva ao aninhamento (callback hell), enquanto Future permite construir cadeias then() planas. A sintaxe async/await torna o código Future ainda mais linear, assemelhando-se ao código síncrono.

Future representa exatamente um resultado assíncrono — uma emissão, após a qual o Future se completa. Ao contrário de Observable (Rx, ReactiveX) ou Flow (Kotlin Coroutines), Future não suporta múltiplos valores ao longo do tempo. Se você precisa de um fluxo de eventos — use Stream em Dart, Observable em Rx ou Flow em Kotlin.

CompletableFuture em Java é um análogo de Promise com uma API estendida: supplyAsync, thenApply, thenCompose, exceptionally. CompletableFuture permite combinar múltiplas operações assíncronas via allOf, anyOf, e também permite especificar um Executor personalizado para execução. Scala Future usa ExecutionContext para gerenciar o pool de threads e suporta composição via for-comprehension.

Em Dart, o padrão Future difere do Promise do JavaScript porque Dart tem tipagem estrita: Future<String> garante o tipo do valor de retorno. Funções async em Dart devem retornar um Future, e o compilador verifica que todos os caminhos retornam um tipo correto. Future.wait é equivalente a Promise.all — recebe Iterable<Future<T>> e retorna Future<List<T>>. Future.delayed e Future.error são fábricas convenientes para testar cenários assíncronos.

Future/Promise é implementado em Python via concurrent.futures.Future e asyncio.Future. concurrent.futures.ThreadPoolExecutor.submit() retorna um Future, no qual se pode chamar result() — uma chamada bloqueante. asyncio.Future é um contêiner compatível com await para um resultado assíncrono no Asyncio. asyncio.gather() executa múltiplas corrotinas em paralelo e retorna uma lista de resultados, similar a Promise.all em JavaScript. Python também usa asyncio.ensure_future baseado em callbacks e cadeias add_done_callback para compor operações assíncronas, mas no código moderno a sintaxe async/await com asyncio.Task é preferida.

No desenvolvimento móvel, Future é ativamente usado em aplicações Flutter. Cada requisição de rede do pacote http ou dio retorna um Future. FutureBuilder é um widget que recebe um Future e um estado de snapshot: connectionDone, hasData, hasError. Quando os dados são recebidos, snapshot.data contém o resultado do Future. StreamBuilder é o análogo para múltiplos valores. FutureBuilder elimina o gerenciamento manual de estado de carregamento via setState.

Scala Future usa ExecutionContext implicitamente — o pool de threads no qual a tarefa assíncrona executa. A composição via map, flatMap, filter funciona porque Future é uma mônada. for-comprehension permite combinar sequencialmente múltiplos Futures sem aninhamento: for { a <- futureA; b <- futureB } yield a + b. Future.sequence funciona como Promise.all. A recuperação de erros é implementada via recover e recoverWith.

Future/Promise em C++ é representado pelas classes std::future e std::promise da biblioteca <future>. std::async lança uma função assíncrona e retorna std::future. std::promise permite definir manualmente um valor via set_value() ou um erro via set_exception(). Ao contrário de Dart e JavaScript, std::future.get() bloqueia a thread até que o resultado seja recebido — esta é uma diferença importante a considerar ao projetar aplicações C++ multithread.

Padrões de Future

Ao projetar APIs que retornam Futures, siga a regra da fonte única de verdade: cada requisição assíncrona é criada uma vez e armazenada em cache via Future.memoize. Se dois componentes solicitam os mesmos dados, eles recebem o mesmo Future — isso evita requisições duplicadas. Para timeout, use Future.timeout (Dart) ou Promise.race com um timeout para garantir que a operação assíncrona seja concluída dentro de um intervalo determinado.

O padrão Retry em Future é implementado através de uma cadeia recursiva: ao erro no catch, a mesma função assíncrona é chamada com um atraso. Exponential backoff aumenta o intervalo entre tentativas: 1 seg — 2 seg — 4 seg — até no máximo 30 seg. Em Dart isso é encapsulado em uma extensão no Future: future.retry(maxRetries: 3, delay: Duration(seconds: 1)). Em Scala, Future.zip combina dois resultados independentes em uma tupla — uma alternativa a Promise.all para dois Futures. Cancelamento não é suportado em Futures padrão, mas é implementado via CancellationToken ou AbortController em JavaScript.

Perguntas frequentes

Qual a diferença entre Future e Promise?

Future é um contêiner somente leitura para ler um resultado assíncrono via then ou await. Promise é um contrato somente escrita que aceita um valor via resolve() e o liga ao Future. Em Dart e JavaScript, estes conceitos estão combinados: Future/Promise é uma classe. Em Java e Scala eles são separados.

Qual a diferença entre Future e Observable?

Future representa um único resultado assíncrono — ele emite exatamente um valor e se completa. Observable (Rx) emite múltiplos valores ao longo do tempo — é um fluxo assíncrono. Se você precisa de uma resposta HTTP — use Future. Se você precisa de um fluxo de alterações de banco de dados — use Observable ou Stream.

O que é async/await e como se relaciona com Future?

async/await é açúcar sintático sobre Future/Promise. A palavra-chave async marca uma função como assíncrona — ela retorna um Future. await pausa a execução até que o Future se complete, sem bloquear a thread. Em Dart, JavaScript, Python e C#, async/await substituiu as cadeias then na maioria dos cenários.

Como tratar erros em uma cadeia Future?

Em Dart, use .catchError() no final da cadeia — ele captura exceções em qualquer estágio. Em JavaScript — .catch(). Dart também tem try/await/catch dentro de funções async. Para recuperação de erros, use .catchError() com um valor padrão ou um novo Future.

O que é Promise.all e quando usá-lo?

Promise.all recebe um array de promessas e retorna uma única Promise que resolve com um array de resultados. Todas as promessas são executadas em paralelo — isso acelera operações independentes (por exemplo, carregar múltiplos arquivos). Se qualquer promessa for rejeitada — todo Promise.all é rejeitado com o mesmo erro.

Resumo

  • Future/Promise — um padrão de programação assíncrona com um contrato para um único valor
  • Future — um contêiner somente leitura para ler o resultado de uma operação
  • Promise — um contrato somente escrita que preenche o Future via resolve/reject
  • Cadeias then — processamento plano de passos assíncronos sem callback hell
  • async/await — açúcar sintático sobre Future, tornando o código linear
  • Promise.all — execução paralela de múltiplas operações assíncronas
  • Para múltiplos valores ao longo do tempo, use Stream ou Observable, não Future

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