Menu
Coddy logo textTech

Futures e async/await

Parte da seção Programação Orientada a Objetos do Journey de Dart da Coddy — lição 76 de 110.

Em aplicações reais, muitas operações levam tempo - buscar dados de um servidor, ler arquivos ou esperar pela entrada do usuário. O Dart lida com isso usando Future, que representa um valor que estará disponível em algum momento no futuro.

Um Future é como uma promessa: "Eu lhe darei o resultado quando estiver pronto." Você pode criar um usando Future.delayed() para simular uma operação que leva tempo:

Future<String> fetchUserName() {
  return Future.delayed(
    Duration(seconds: 1),
    () => 'Alice',
  );
}

Para trabalhar com o resultado de um Future, use async e await. Marque sua função como async, então use await para pausar a execução até que o Future seja concluído:

Future<void> main() async {
  print('Fetching user...');
  String name = await fetchUserName();
  print('Hello, $name!');
}

Future<String> fetchUserName() {
  return Future.delayed(
    Duration(seconds: 1),
    () => 'Alice',
  );
}

Sem o await, você obteria um Future<String> em vez da string real. A palavra-chave await "desembrulha" o Future e fornece o valor interno. Observe que qualquer função que utilize await deve ser marcada como async, e ela retorna automaticamente um Future.

Você também pode retornar valores diretamente de funções assíncronas - o Dart os envolve em um Future automaticamente:

Future<int> calculateTotal() async {
  var a = await fetchNumber();
  var b = await fetchNumber();
  return a + b;  // Envolvido automaticamente em Future<int>
}
challenge icon

Desafio

Fácil

Vamos construir um serviço meteorológico que simula a busca de dados climáticos de diferentes cidades! Você praticará o uso de Future, async, e await para lidar com operações que levam tempo para serem concluídas.

Você organizará seu código em dois arquivos:

  • weather_service.dart: Crie uma classe WeatherService que simula a busca de informações meteorológicas. Sua classe deve ter:
    • Um método fetchTemperature(String city) que retorna um Future<int>. Use Future.delayed() com uma duração de 100 milissegundos para simular o atraso da rede. O método deve retornar uma temperatura baseada no nome da cidade: retorne o comprimento do nome da cidade multiplicado por 3.
    • Um método fetchCondition(String city) que retorna um Future<String>. Use Future.delayed() com 100 milissegundos de atraso. Retorne 'Sunny' se o nome da cidade tiver um número par de caracteres, caso contrário, retorne 'Cloudy'.
    • Um método assíncrono getFullReport(String city) que retorna um Future<String>. Este método deve aguardar (await) tanto fetchTemperature quanto fetchCondition, e então retornar uma string formatada: '[city]: [temperature]C, [condition]'
  • main.dart: Importe seu serviço meteorológico e demonstre como as operações assíncronas funcionam. Sua função main deve ser assíncrona e:
    • Criar uma instância de WeatherService
    • Imprimir Fetching weather data...
    • Aguardar e imprimir o relatório completo para 'Paris'
    • Aguardar e imprimir o relatório completo para 'Tokyo'
    • Aguardar e imprimir o relatório completo para 'London'
    • Imprimir Done!

Observe como cada chamada para getFullReport espera que tanto a temperatura quanto a condição sejam buscadas antes de retornar o resultado combinado. A palavra-chave await pausa a execução até que cada Future seja concluído!

Saída esperada:

Fetching weather data...
Paris: 15C, Cloudy
Tokyo: 15C, Cloudy
London: 18C, Sunny
Done!

Folha de consulta

Um Future representa um valor que estará disponível no futuro. Ele é usado para operações que levam tempo, como buscar dados ou ler arquivos.

Crie um Future usando Future.delayed():

Future<String> fetchUserName() {
  return Future.delayed(
    Duration(seconds: 1),
    () => 'Alice',
  );
}

Use async e await para trabalhar com Futures. Marque a função como async e use await para pausar a execução até que o Future seja concluído:

Future<void> main() async {
  print('Fetching user...');
  String name = await fetchUserName();
  print('Hello, $name!');
}

A palavra-chave await "desembrulha" o Future e fornece o valor real. Sem ela, você obteria um Future<String> em vez da string.

Qualquer função que utilize await deve ser marcada como async e retorna automaticamente um Future.

Os valores de retorno de funções assíncronas são automaticamente envolvidos em um Future:

Future<int> calculateTotal() async {
  var a = await fetchNumber();
  var b = await fetchNumber();
  return a + b;  // Automatically wrapped in Future<int>
}

Experimente você mesmo

import 'weather_service.dart';

Future<void> main() async {
  // TODO: Criar uma instância de WeatherService
  
  // TODO: Imprimir 'Fetching weather data...'
  
  // TODO: Aguardar e imprimir o relatório completo para 'Paris'
  
  // TODO: Aguardar e imprimir o relatório completo para 'Tokyo'
  
  // TODO: Aguardar e imprimir o relatório completo para 'London'
  
  // TODO: Imprimir 'Done!'
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos