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/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.
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 é 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.
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.
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 é 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.
O primeiro exemplo — criar um Future através de uma função async e tratá-lo com then/catchError:
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:
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:
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Concluído")
}, 1000)
})
promise
.then(value => console.log(value))
.catch(err => console.error(err))
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.
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
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.
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.
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.
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.
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
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