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

Introducción a Futures y Promises

Comprenda los conceptos fundamentales de `Future` para resultados asíncronos y `Promise` para completarlos.

Introducción a Futures y Promises es una lección gratuita de Scala for Backend Engineering & Functional Programming en CoddyKit. Esta es la lección 1 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.

Código asíncrono: por qué es importante

En programación, las tareas pueden ejecutarse de forma síncrona (una después de otra) o asíncrona (las tareas pueden comenzar sin esperar a que terminen las anteriores).

La programación asíncrona es esencial para crear aplicaciones interactivas que no se bloqueen mientras esperan operaciones lentas, como solicitudes de red o consultas a bases de datos.

El problema de las llamadas bloqueantes

Imagine que su programa necesita obtener datos de Internet. Si esta operación es bloqueante, el programa se pausará y no hará nada más hasta que lleguen los datos.

Esto puede provocar que la interfaz de usuario se «congele» o generar aplicaciones del lado del servidor ineficientes. Necesitamos una forma de realizar estas tareas en segundo plano sin detener el flujo principal.

Introducción a Scala Futures

El Future de Scala es una herramienta potente para la programación asíncrona. Representa un valor que quizá aún no esté disponible, pero que lo estará en algún momento futuro.

  • Considérelo como pedir un café: recibe un comprobante (el Future) y puede hacer otras cosas mientras preparan su café.
  • Cuando el café está listo, el comprobante se «completa» con su bebida (el resultado).

Cómo crear su primer Future

Puede crear un Future envolviendo un cálculo en Future { ... }. Este cálculo se ejecutará en un hilo independiente.

Se necesita un ExecutionContext para programar estas tareas. Para simplificar, usaremos uno global.

import scala.concurrent.{Future, ExecutionContext}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success}

object Main extends App {
  println("Starting computation...")

  val f: Future[Int] = Future {
    Thread.sleep(1000) // Simulate a long operation
    42
  }

  f.onComplete {
    case Success(value) => println(s"Result: $value")
    case Failure(e) => println(s"Error: ${e.getMessage}")
  }

  println("Computation started, continuing...")
  // Keep main thread alive for a bit to see Future's result
  Thread.sleep(2000)
}

Comprender ExecutionContext

Un ExecutionContext es, básicamente, un conjunto de hilos donde se ejecutan los cálculos asíncronos.

  • Gestiona cómo y cuándo se ejecutan las tareas.
  • En ejemplos breves, suele utilizarse scala.concurrent.ExecutionContext.Implicits.global, que proporciona un conjunto de hilos predeterminado.
  • En aplicaciones reales, puede configurar conjuntos de hilos específicos para controlar mejor el uso de recursos.

Gestión de resultados de Future: onComplete

El método onComplete se utiliza para definir qué ocurre cuando finaliza un Future, tanto si tiene éxito como si falla.

Recibe una función que opera sobre un scala.util.Try, que puede ser Success(value) o Failure(exception).

import scala.concurrent.{Future, ExecutionContext}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success}

object Main extends App {
  val futureSuccess = Future { 10 / 2 }
  val futureFailure = Future { 10 / 0 }

  futureSuccess.onComplete {
    case Success(result) => println(s"Success: $result")
    case Failure(e) => println(s"Error: ${e.getMessage}")
  }

  futureFailure.onComplete {
    case Success(result) => println(s"Success: $result")
    case Failure(e) => println(s"Error: ${e.getMessage}")
  }

  Thread.sleep(100) // Allow Futures to complete and print
}

Controladores simplificados: Success/Failure

Para casos más sencillos, puede utilizar onSuccess y onFailure para gestionar únicamente los resultados correctos o únicamente los errores, respectivamente.

  • onSuccess recibe una función para el valor correcto.
  • onFailure recibe una función para la excepción.
  • Estos son métodos de conveniencia basados en onComplete.
import scala.concurrent.{Future, ExecutionContext}
import scala.concurrent.ExecutionContext.Implicits.global

object Main extends App {
  val futureValue = Future { "Hello, Scala!" }

  futureValue.onSuccess { case msg => println(s"Got message: $msg") }
  futureValue.onFailure { case e => println(s"Oops, an error: ${e.getMessage}") }

  val futureError = Future { throw new RuntimeException("Something broke!") }

  futureError.onSuccess { case msg => println(s"Got message: $msg") }
  futureError.onFailure { case e => println(s"Oops, an error: ${e.getMessage}") }

  Thread.sleep(100) // Allow Futures to complete and print
}

¿Qué es un Promise de Scala?

Mientras que un Future es un marcador de posición de solo lectura para un resultado, un Promise es un contenedor que se escribe una sola vez y que puede completarse con un valor o una excepción.

  • Un Promise se utiliza para completar un Future.
  • Se crea un Promise, se obtiene su Future asociado y, después, se completa el Promise cuando el resultado está listo.

Completar un Promise

Puede completar un Promise mediante sus métodos success() o failure(). Una vez completado un Promise, su Future asociado también se completará.

Intentar completar un Promise más de una vez provocará un error.

import scala.concurrent.{Future, Promise, ExecutionContext}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success}

object Main extends App {
  val p = Promise[String]() // Create a Promise that will hold a String
  val f: Future[String] = p.future // Get the Future associated with the Promise

  f.onComplete {
    case Success(value) => println(s"Future completed with: '$value'")
    case Failure(e) => println(s"Future failed with: ${e.getMessage}")
  }

  // Simulate an async operation completing the promise
  Future {
    Thread.sleep(500)
    p.success("Data fetched successfully!") // Complete the Promise
  }

  println("Promise created, waiting for completion...")
  Thread.sleep(1000) // Keep main thread alive to see Future's result
}

Futures y Promises en conjunto

Future y Promise suelen trabajar conjuntamente. Un patrón habitual consiste en utilizar un Promise cuando necesita controlar manualmente la finalización de un Future, por ejemplo, desde un sistema externo o una API antigua basada en callbacks.

Esto permite envolver operaciones asíncronas que no se basan en Future en el modelo de Future, haciéndolas compatibles con código basado en Future.

import scala.concurrent.{Future, Promise, ExecutionContext}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success}

object Main extends App {
  def performLongTask(data: String): Future[String] = {
    val p = Promise[String]()
    // Simulate an external system or callback-based API
    Future {
      Thread.sleep(700)
      if (data == "fail") p.failure(new Exception("Task failed!"))
      else p.success(s"Processed: $data")
    }
    p.future // Return the Future that will be completed by the Promise
  }

  val task1 = performLongTask("input data")
  task1.onComplete { case Success(res) => println(s"Task 1: $res") case Failure(e) => println(s"Task 1: ${e.getMessage}") }

  val task2 = performLongTask("fail")
  task2.onComplete { case Success(res) => println(s"Task 2: $res") case Failure(e) => println(s"Task 2: ${e.getMessage}") }

  Thread.sleep(1500) // Keep main thread alive for results
}

Comprobación rápida: Future frente a Promise

¿Cuál de las siguientes afirmaciones describe correctamente las funciones de Future y Promise en Scala?

Resumen: Futures y Promises

¡Excelente trabajo! En esta lección ha aprendido los fundamentos de la programación asíncrona en Scala:

  • Future: un marcador de posición para un resultado que estará disponible en algún momento.
  • Promise: un contenedor que se escribe una sola vez y que se utiliza para completar manualmente un Future.
  • ExecutionContext: programa la ejecución de tareas asíncronas.
  • Cómo gestionar los resultados de Future mediante onComplete, onSuccess y onFailure.

Estos conceptos son los componentes básicos de patrones asíncronos más complejos.

Preguntas frecuentes

¿La lección «Introducción a Futures y Promises» es gratis?

Sí — el texto completo de «Introducción a Futures y Promises» 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 «Introducción a Futures y Promises»?

Comprenda los conceptos fundamentales de `Future` para resultados asíncronos y `Promise` para completarlos. 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 1 de 3.

¿Cuánto tiempo toma la lección «Introducción a Futures y Promises»?

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