0Pricing
Scala for Backend Engineering & Functional Programming · Aula

Composição de operações assíncronas

Aprenda a encadear e combinar vários `Futures` usando métodos como `map`, `flatMap` e compreensões `for`.

Composição de operações assíncronas é uma aula grátis de Scala for Backend Engineering & Functional Programming no CoddyKit. Esta é a aula 2 de 3. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Scala for Backend Engineering & Functional Programming, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Scala for Backend Engineering & Functional Programming inclui 3 aulas no total.

Por que encadear operações assíncronas?

Os Futures ajudam a executar tarefas sem bloquear o programa principal. Mas e se o resultado de uma tarefa for necessário para outra, ou se precisarmos combinar os resultados de várias tarefas?

É aí que a composição de Futures se torna útil. Você aprenderá a encadear e combinar essas operações assíncronas, tornando seu código Scala mais poderoso e responsivo.

`map`: transformar o resultado de um Future

O método map é usado quando você tem um Future e deseja transformar seu resultado bem-sucedido em outro valor. A função de transformação fornecida será aplicada assim que o Future for concluído com sucesso.

  • Ele sempre retorna um novo Future.
  • É ideal para transformações simples e síncronas em um resultado assíncrono.

`map` em ação (código)

Aqui, obtemos um número de um Future e depois o duplicamos usando map. A transformação ocorre somente depois que o Future inicial é concluído.

import scala.concurrent.{Future, Await}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._

object Main {
  def main(args: Array[String]): Unit = {
    val originalFuture: Future[Int] = Future {
      Thread.sleep(100) // Simulate work
      10
    }

    val doubledFuture: Future[Int] = originalFuture.map(value => value * 2)

    val result = Await.result(doubledFuture, 1.second)
    println(s"Doubled value: $result")
  }
}

`flatMap`: encadeando Futures

Às vezes, o resultado bem-sucedido de um Future precisa iniciar outro Future. É aí que flatMap se destaca. Ele "achata" um Future de um Future (Future[Future[T]]) em um único Future[T].

  • Use-o quando sua função de transformação retornar um Future.
  • Ele é essencial para operações assíncronas sequenciais.

`flatMap` em ação (código)

Buscamos um ID de usuário e depois usamos esse ID para buscar os detalhes do usuário. Cada etapa é uma operação assíncrona que retorna um Future. flatMap garante que elas sejam executadas em sequência.

import scala.concurrent.{Future, Await}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._

object Main {
  def main(args: Array[String]): Unit = {
    def fetchUserId(): Future[Int] = Future {
      Thread.sleep(50)
      123
    }

    def fetchUserDetails(userId: Int): Future[String] = Future {
      Thread.sleep(100)
      s"User $userId details"
    }

    val userDetailsFuture: Future[String] = fetchUserId().flatMap { userId =>
      fetchUserDetails(userId)
    }

    val result = Await.result(userDetailsFuture, 1.second)
    println(s"Details: $result")
  }
}

`map` vs. `flatMap`: diferença fundamental

É comum confundir map e flatMap. Lembre-se:

  • map: sua função retorna um valor comum (por exemplo, Int, String). Future[A].map(A => B) resulta em Future[B].
  • flatMap: sua função retorna outro Future (por exemplo, Future[Int], Future[String]). Future[A].flatMap(A => Future[B]) resulta em Future[B].

flatMap serve para encadear operações assíncronas, enquanto map serve para transformar um resultado assíncrono de forma síncrona.

Compreensões `for`: encadeamento elegante

As compreensões for do Scala fornecem uma sintaxe clara e legível para encadear operações que envolvem map e flatMap. Elas são apenas açúcar sintático, o que significa que o compilador as transforma em uma série de chamadas a map, flatMap e filter.

Quando você tem várias operações dependentes com Future, as compreensões for fazem o código parecer quase síncrono.

Código de uma compreensão `for`

Este exemplo usa uma compreensão for para encadear a mesma lógica de busca do ID e dos detalhes do usuário que vimos com flatMap. Observe como o código fica mais limpo!

import scala.concurrent.{Future, Await}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._

object Main {
  def main(args: Array[String]): Unit = {
    def fetchUserId(): Future[Int] = Future {
      Thread.sleep(50)
      123
    }

    def fetchUserName(userId: Int): Future[String] = Future {
      Thread.sleep(100)
      s"Alice (ID: $userId)"
    }

    val userFuture: Future[String] = for {
      id <- fetchUserId()
      name <- fetchUserName(id)
    } yield name

    val result = Await.result(userFuture, 1.second)
    println(s"User name: $result")
  }
}

`zip`: combinando resultados independentes

E se você tiver dois independentes Futures e quiser combinar seus resultados assim que ambos forem concluídos? O método zip é perfeito para isso. Ele recebe outro Future e retorna um novo Future que contém um par (uma Tuple) com os resultados bem-sucedidos de ambos.

Os dois futures são executados simultaneamente, e zip espera que ambos terminem.

import scala.concurrent.{Future, Await}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._

object Main {
  def main(args: Array[String]): Unit = {
    val futureA = Future {
      Thread.sleep(100)
      "Hello"
    }

    val futureB = Future {
      Thread.sleep(50)
      "World"
    }

    val combinedFuture: Future[(String, String)] = futureA.zip(futureB)

    val (greeting, subject) = Await.result(combinedFuture, 1.second)
    println(s"$greeting $subject!")
  }
}

Verificação rápida: compondo Futures

Considere o seguinte trecho de código Scala. Qual será o valor final impresso?

import scala.concurrent.{Future, Await}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._

object Main {
  def main(args: Array[String]): Unit = {
    val f1 = Future { 5 }
    val f2 = f1.map(x => x + 2)
    val f3 = f2.flatMap(y => Future { y * 3 })

    val result = Await.result(f3, 1.second)
    println(result)
  }
}

Recapitulação: encadeando tarefas assíncronas

Você aprendeu maneiras poderosas de compor Futures em Scala:

  • map: transforma o resultado bem-sucedido de um Future em um novo valor.
  • flatMap: encadeia dois Futures, usando o resultado do primeiro para iniciar o segundo.
  • compreensões for: fornecem uma sintaxe clara, semelhante à síncrona, para cadeias de flatMap e map.
  • zip: combina os resultados de dois Futures independentes em uma tupla.

Essas ferramentas são essenciais para criar aplicações assíncronas responsivas e eficientes em Scala!

Perguntas Frequentes

A aula “Composição de operações assíncronas” é grátis?

Sim — o texto completo de “Composição de operações assíncronas” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Scala for Backend Engineering & Functional Programming, atualize para CoddyKit PRO. O curso de Scala for Backend Engineering & Functional Programming inclui 3 aulas no total.

O que vou aprender em “Composição de operações assíncronas”?

Aprenda a encadear e combinar vários `Futures` usando métodos como `map`, `flatMap` e compreensões `for`. Você pratica Scala for Backend Engineering & Functional Programming com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Scala for Backend Engineering & Functional Programming?

Nenhuma experiência prévia é necessária. Scala for Backend Engineering & Functional Programming no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 3.

Quanto tempo leva a aula “Composição de operações assíncronas”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Scala for Backend Engineering & Functional Programming?

Sim. Cada aula de Scala for Backend Engineering & Functional Programming inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Introdução a Futures e Promises
  2. Composição de operações assíncronas
  3. Tratamento de erros em Futures
← Voltar para Scala for Backend Engineering & Functional Programming