0Pricing
Scala for Backend Engineering & Functional Programming · Lección

Composición de operaciones asíncronas

Aprenda a encadenar y combinar varios `Futures` mediante métodos como `map`, `flatMap` y las comprensiones `for`.

Composición de operaciones asíncronas es una lección gratuita de Scala for Backend Engineering & Functional Programming en CoddyKit. Esta es la lección 2 de 3. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Scala for Backend Engineering & Functional Programming, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Scala for Backend Engineering & Functional Programming incluye 3 lecciones en total.

¿Por qué encadenar operaciones asíncronas?

Los Futures nos ayudan a ejecutar tareas sin bloquear el programa principal. Pero ¿qué ocurre si el resultado de una tarea se necesita para otra o si necesitamos combinar los resultados de varias tareas?

Aquí es donde resulta útil componer Futures. Aprenderemos a encadenar y combinar estas operaciones asíncronas para que su código Scala sea más potente y receptivo.

`map`: transformar el resultado de un Future

El método map se utiliza cuando tiene un Future y quiere transformar su resultado correcto en otro valor. La función de transformación que proporcione se aplicará cuando el Future se complete correctamente.

  • Siempre devuelve un nuevo Future.
  • Es ideal para transformaciones sencillas y síncronas de un resultado asíncrono.

`map` en acción (código)

Aquí obtenemos un número de un Future y después lo duplicamos mediante map. La transformación solo tiene lugar cuando finaliza el Future inicial.

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`: encadenar Futures

A veces, el resultado correcto de un Future debe iniciar otro Future. Aquí es donde flatMap resulta especialmente útil. «Aplana» un Future de un Future (Future[Future[T]]) en un único Future[T].

  • Úselo cuando su función de transformación devuelva un Future.
  • Es esencial para las operaciones asíncronas secuenciales.

`flatMap` en acción (código)

Obtenemos un ID de usuario y, después, usamos ese ID para obtener los detalles del usuario. Cada paso es una operación asíncrona que devuelve un Future. flatMap garantiza que se ejecuten en secuencia.

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` frente a `flatMap`: diferencia clave

Es habitual confundir map y flatMap. Recuerde:

  • map: su función devuelve un valor normal (por ejemplo, Int o String). Future[A].map(A => B) da como resultado Future[B].
  • flatMap: su función devuelve otro Future (por ejemplo, Future[Int] o Future[String]). Future[A].flatMap(A => Future[B]) da como resultado Future[B].

flatMap sirve para encadenar operaciones asíncronas, mientras que map sirve para transformar de forma síncrona un resultado asíncrono.

Composiciones `for`: encadenamiento elegante

Las comprensiones for de Scala proporcionan una sintaxis clara y legible para encadenar operaciones que implican map y flatMap. Son únicamente azúcar sintáctico, lo que significa que el compilador las traduce en una serie de llamadas a map, flatMap y filter.

Cuando tiene varias operaciones dependientes con Future, las comprensiones for hacen que el código parezca casi síncrono.

Código de comprensión de `for`

Este ejemplo utiliza una comprensión for para encadenar la misma lógica de obtención del ID y los detalles del usuario que vimos con flatMap. ¡Observe lo mucho más limpio que resulta!

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`: combinación de resultados independientes

¿Qué ocurre si tiene dos Future independientes y quiere combinar sus resultados cuando ambos se hayan completado? El método zip es perfecto para esto. Toma otro Future y devuelve un nuevo Future que contiene un par (un Tuple) con sus resultados correctos.

Ambos futures se ejecutan simultáneamente y zip espera a que los dos terminen.

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!")
  }
}

Comprobación rápida: composición de Futures

Considere el siguiente fragmento de código Scala. ¿Cuál será el valor final que se imprimirá?

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)
  }
}

Resumen: encadenamiento de tareas asíncronas

Ha aprendido formas eficaces de componer Future en Scala:

  • map: transforma el resultado correcto de un Future en un valor nuevo.
  • flatMap: encadena dos Future utilizando el resultado del primero para iniciar el segundo.
  • Comprensiones for: proporcionan una sintaxis clara, similar a la síncrona, para encadenar flatMap y map.
  • zip: combina los resultados de dos Future independientes en una tupla.

¡Estas herramientas son fundamentales para crear aplicaciones asíncronas eficientes y con buena capacidad de respuesta en Scala!

Preguntas frecuentes

¿La lección «Composición de operaciones asíncronas» es gratis?

Sí — el texto completo de «Composición de operaciones asíncronas» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Scala for Backend Engineering & Functional Programming, actualiza a CoddyKit PRO. El curso de Scala for Backend Engineering & Functional Programming incluye 3 lecciones en total.

¿Qué aprenderé en «Composición de operaciones asíncronas»?

Aprenda a encadenar y combinar varios `Futures` mediante métodos como `map`, `flatMap` y las comprensiones `for`. Practicas Scala for Backend Engineering & Functional Programming con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Scala for Backend Engineering & Functional Programming?

No se requiere experiencia previa. Scala for Backend Engineering & Functional Programming en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 2 de 3.

¿Cuánto tiempo toma la lección «Composición de operaciones asíncronas»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Scala for Backend Engineering & Functional Programming?

Sí. Cada lección de Scala for Backend Engineering & Functional Programming incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Introducción a Futures y Promises
  2. Composición de operaciones asíncronas
  3. Gestión de errores en Futures
← Volver a Scala for Backend Engineering & Functional Programming