Mobile App Development · Dart/Flutter

20 · Async/Await — Exercícios

Coloque em prática o que viu no conteúdo: Future, async/await, erro assíncrono, Future.wait e Stream.

Exercício

exercicio_01_future_simples.dart

Cria a função buscarNome(), que retorna um Future<String> usando Future.delayed com 300ms de atraso. Em main, await pausa a execução até o Future ser resolvido, para então imprimir o nome carregado.

// Demonstração de Future simples em Dart.
// Future<T> representa um valor que estará disponível no futuro (operação assíncrona).
// 'await' pausa a execução da função até o Future ser resolvido.
// A função que usa 'await' precisa ser marcada como 'async'.

// Simula uma busca assíncrona que retorna um nome após 300ms de delay.
Future<String> buscarNome() {
  // Future.delayed() cria um Future que só resolve após o tempo especificado.
  // O segundo argumento é uma função que retorna o valor do Future.
  return Future.delayed(Duration(milliseconds: 300), () => 'Ana');
}

// main() é 'async' porque usa 'await' para esperar o Future.
Future<void> main() async {
  // 'await' pausa a execução até buscarNome() retornar o valor.
  // Sem 'await', 'nome' seria um Future<String>, não uma String.
  String nome = await buscarNome();
  print('Nome carregado: $nome');
}

Saída esperada

Nome carregado: Ana

Como executar

dart run 20-Async_Await/02_Exercicios/codigo_fonte/exercicio_01_future_simples.dart

Exercício

exercicio_02_async_await.dart

A função buscarMensagem() é marcada com async e usa await Future.delayed(...) internamente. Em main, a primeira linha é impressa imediatamente; só depois dos 300ms de delay é que await buscarMensagem() resolve e a segunda linha aparece.

// Demonstração de funções assíncronas com 'async' e 'await'.
// 'async' marca a função como assíncrona, permitindo usar 'await' dentro dela.
// Funções 'async' sempre retornam um Future, mesmo que o retorno declarado seja String.

// Função assíncrona que simula uma chamada de rede com delay de 300ms.
Future<String> buscarMensagem() async {
  // 'await' pausa esta função por 300ms sem bloquear a thread principal.
  await Future.delayed(Duration(milliseconds: 300));
  // Após o delay, retorna a mensagem normalmente.
  return 'Dados recebidos com sucesso';
}

Future<void> main() async {
  // Informa ao usuário que a busca começou — exibido antes do delay.
  print('Buscando mensagem...');
  // 'await' espera buscarMensagem() terminar antes de continuar.
  String mensagem = await buscarMensagem();
  // Exibido apenas após os 300ms de delay simulado.
  print(mensagem);
}

Saída esperada

Buscando mensagem...
Dados recebidos com sucesso

Como executar

dart run 20-Async_Await/02_Exercicios/codigo_fonte/exercicio_02_async_await.dart

Exercício

exercicio_03_carregamento.dart

Simula o carregamento de um perfil de usuário retornando um Future<Map<String, dynamic>>. A mensagem "Carregando perfil..." aparece antes do await; o mapa só fica disponível depois do delay, e seus valores são acessados pelas chaves 'nome' e 'nivel'.

// Demonstração de carregamento assíncrono de dados estruturados.
// Simula o carregamento de um perfil de usuário de uma API remota.
// Future<Map<String, dynamic>> retorna um mapa com os dados do perfil.

// Simula a busca de dados de perfil com delay de 300ms (latência de rede).
Future<Map<String, dynamic>> carregarPerfil() async {
  // Simula o tempo de resposta de uma chamada de API real.
  await Future.delayed(Duration(milliseconds: 300));

  // Retorna o mapa com os dados do perfil após o delay simulado.
  return {'nome': 'Ana', 'nivel': 'iniciante'};
}

Future<void> main() async {
  // Mensagem exibida enquanto aguarda a resposta assíncrona.
  print('Carregando perfil...');
  // Aguarda o Future e obtém o mapa de dados do perfil.
  Map<String, dynamic> perfil = await carregarPerfil();
  // Acessa os valores do mapa pelas suas chaves.
  print('Nome: ${perfil['nome']}');
  print('Nivel: ${perfil['nivel']}');
}

Saída esperada

Carregando perfil...
Nome: Ana
Nivel: iniciante

Como executar

dart run 20-Async_Await/02_Exercicios/codigo_fonte/exercicio_03_carregamento.dart

Exercício

exercicio_04_erro_assincrono.dart

A função buscarProduto() aguarda 300ms e então lança uma Exception com throw — o que faz o Future ser rejeitado. Em main, o try/catch envolve o await buscarProduto() e captura a exceção normalmente, como em código síncrono.

// Demonstração de tratamento de erros em operações assíncronas.
// Erros em funções 'async' são capturados com try/catch normalmente,
// da mesma forma que em código síncrono.

// Simula uma busca que falha com uma Exception após 300ms.
Future<String> buscarProduto() async {
  await Future.delayed(Duration(milliseconds: 300));
  // 'throw' em uma função 'async' faz o Future ser rejeitado com a exceção.
  throw Exception('Produto nao encontrado');
}

Future<void> main() async {
  // try/catch captura exceções lançadas em operações aguardadas com 'await'.
  try {
    // 'await' recebe o valor resolvido ou propaga a exceção se o Future falhar.
    String produto = await buscarProduto();
    print(produto);
  } catch (erro) {
    // Captura a Exception lançada por buscarProduto() e exibe mensagem de erro.
    print('Erro ao buscar produto: $erro');
  }
}

Saída esperada

Erro ao buscar produto: Exception: Produto nao encontrado

Como executar

dart run 20-Async_Await/02_Exercicios/codigo_fonte/exercicio_04_erro_assincrono.dart

Exercício

exercicio_05_future_wait.dart

buscarUsuario() e buscarPedidos() têm 300ms de latência cada. Future.wait as executa em paralelo — o tempo total é de ~300ms em vez de ~600ms — e retorna uma List<String> com os resultados na mesma ordem em que os Futures foram passados na lista, independentemente de qual terminou primeiro.

// Demonstração de Future.wait para executar múltiplos Futures em paralelo.
// Future.wait recebe uma lista de Futures e aguarda todos concluírem
// simultaneamente — mais eficiente do que aguardá-los um a um com 'await'.

// Simula a busca de dados do usuário (300ms de latência).
Future<String> buscarUsuario() async {
  await Future.delayed(Duration(milliseconds: 300));
  return 'Usuario carregado';
}

// Simula a busca dos pedidos do usuário (300ms de latência).
Future<String> buscarPedidos() async {
  await Future.delayed(Duration(milliseconds: 300));
  return 'Pedidos carregados';
}

Future<void> main() async {
  // Future.wait executa ambas as funções em paralelo.
  // O tempo total é ~300ms (o maior) em vez de ~600ms (somados sequencialmente).
  // Retorna uma List<String> com os resultados na mesma ordem da lista de entrada.
  List<String> resultados = await Future.wait([
    buscarUsuario(),
    buscarPedidos(),
  ]);

  // Percorre e exibe cada resultado retornado em paralelo.
  for (String resultado in resultados) {
    print(resultado);
  }
}

Saída esperada

Usuario carregado
Pedidos carregados

Como executar

dart run 20-Async_Await/02_Exercicios/codigo_fonte/exercicio_05_future_wait.dart

Exercício

exercicio_06_stream_basica.dart

A função geradora contador() usa async* e yield para emitir os números 1, 2 e 3, um a cada 200ms. Em main, await for recebe cada valor assim que ele é emitido e imprime, na ordem, até a Stream se encerrar.

// Demonstração de Stream básica em Dart.
// Stream é uma sequência de eventos assíncronos — valores que chegam ao longo do tempo.
// Diferença de Future: Future resolve uma vez; Stream emite múltiplos valores.
// 'async*' marca uma função geradora assíncrona que usa 'yield' para emitir valores.

// Gera uma Stream que emite os números 1, 2 e 3 com 200ms entre cada emissão.
Stream<int> contador() async* {
  for (int numero = 1; numero <= 3; numero++) {
    // Aguarda 200ms antes de emitir o próximo valor.
    await Future.delayed(Duration(milliseconds: 200));
    // 'yield' emite o valor atual para os ouvintes da Stream.
    // A função não encerra aqui — continua para a próxima iteração.
    yield numero;
  }
}

Future<void> main() async {
  // 'await for' itera sobre cada valor emitido pela Stream conforme chegam.
  // O laço só termina quando a Stream for encerrada (após o último 'yield').
  await for (int numero in contador()) {
    print('Numero recebido: $numero');
  }
}

Saída esperada

Numero recebido: 1
Numero recebido: 2
Numero recebido: 3

Como executar

dart run 20-Async_Await/02_Exercicios/codigo_fonte/exercicio_06_stream_basica.dart