Introduzione a Future e Promise
Comprenda i concetti fondamentali di `Future` per i risultati asincroni e di `Promise` per completarli.
Introduzione a Future e Promise è una lezione Scala for Backend Engineering & Functional Programming gratuita su CoddyKit. Questa è la lezione 1 di 3. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Scala for Backend Engineering & Functional Programming, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Scala for Backend Engineering & Functional Programming include 3 lezioni in totale.
Codice asincrono: perché è importante
In programmazione, le attività possono essere eseguite in modo sincrono (una dopo l'altra) o asincrono (le attività possono iniziare senza aspettare che quelle precedenti siano terminate).
La programmazione asincrona è fondamentale per creare applicazioni reattive che non si bloccano in attesa di operazioni lente, come le richieste di rete o le query al database.
Il problema delle chiamate bloccanti
Immagini che il programma debba recuperare dati da Internet. Se questa operazione è bloccante, il programma si fermerà e non farà altro finché i dati non saranno arrivati.
Questo può causare un'interfaccia utente "bloccata" o applicazioni lato server inefficienti. È necessario un modo per eseguire queste attività in background senza interrompere il flusso principale.
Introduzione alle Future di Scala
La Future di Scala è uno strumento potente per la programmazione asincrona. Rappresenta un valore che potrebbe non essere ancora disponibile, ma lo sarà in futuro.
- La si può immaginare come l'ordinazione di un caffè: si riceve uno scontrino (la
Future) e si possono svolgere altre attività mentre il caffè viene preparato. - Quando il caffè è pronto, lo scontrino viene "completato" con la bevanda (il risultato).
Creare la prima Future
È possibile creare una Future racchiudendo un calcolo in Future { ... }. Questo calcolo verrà eseguito in un thread separato.
Per pianificare queste attività è necessario un ExecutionContext. Per semplicità, ne useremo uno globale.
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)
}Comprendere ExecutionContext
Un ExecutionContext è essenzialmente un pool di thread in cui vengono eseguiti i calcoli asincroni.
- Gestisce come e quando vengono eseguite le attività.
- Per esempi rapidi, si usa spesso
scala.concurrent.ExecutionContext.Implicits.global, che fornisce un pool di thread predefinito. - Nelle applicazioni reali, è possibile configurare pool di thread specifici per controllare meglio l'uso delle risorse.
Gestire i risultati di Future: onComplete
Il metodo onComplete serve a definire cosa accade quando una Future termina, sia in caso di successo sia in caso di errore.
Riceve una funzione che opera su una scala.util.Try, che può essere 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
}Gestori semplificati: Success/Failure
Per i casi più semplici, è possibile usare onSuccess e onFailure per gestire rispettivamente solo i risultati corretti o solo gli errori.
onSuccessriceve una funzione per il valore restituito con successo.onFailurericeve una funzione per l'eccezione.- Sono metodi di praticità costruiti sopra
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
}Che cos'è una Promise di Scala?
Mentre una Future è un segnaposto in sola lettura per un risultato, una Promise è un contenitore scrivibile una sola volta, che può essere completato con un valore o un'eccezione.
- Una
Promiseviene usata per completare unaFuture. - Si crea una
Promise, si ottiene laFutureassociata e quindi si completa laPromisequando il risultato è pronto.
Completare una Promise
È possibile completare una Promise usando i metodi success() o failure(). Una volta completata una Promise, anche la Future associata verrà completata.
Il tentativo di completare una Promise più di una volta genera un errore.
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
}Future e Promise insieme
Future e Promise spesso lavorano insieme. Un modello comune consiste nell'usare una Promise quando è necessario controllare manualmente il completamento di una Future, ad esempio tramite un sistema esterno o un'API meno recente basata sui callback.
Questo consente di racchiudere nel modello Future operazioni asincrone non basate su Future, rendendole compatibili con il codice basato sulle 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
}Verifica rapida: Future e Promise a confronto
Quali delle seguenti affermazioni descrivono correttamente i ruoli di Future e Promise in Scala?
Riepilogo: Future e Promise
Ottimo lavoro! In questa lezione sono stati appresi i fondamenti della programmazione asincrona in Scala:
Future: un segnaposto per un risultato che sarà disponibile in futuro.Promise: un contenitore a scrittura singola usato per completare manualmente unFuture.ExecutionContext: pianifica l'esecuzione delle attività asincrone.- Come gestire i risultati di
FutureusandoonComplete,onSuccesseonFailure.
Questi concetti sono gli elementi fondamentali per creare pattern asincroni più complessi!
Domande Frequenti
La lezione «Introduzione a Future e Promise» è gratuita?
Sì — il testo completo di «Introduzione a Future e Promise» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Scala for Backend Engineering & Functional Programming, passa a CoddyKit PRO. Il corso Scala for Backend Engineering & Functional Programming include 3 lezioni in totale.
Cosa imparerò in «Introduzione a Future e Promise»?
Comprenda i concetti fondamentali di `Future` per i risultati asincroni e di `Promise` per completarli. Eserciti Scala for Backend Engineering & Functional Programming con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Scala for Backend Engineering & Functional Programming?
Non è richiesta alcuna esperienza precedente. Scala for Backend Engineering & Functional Programming su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 3.
Quanto tempo richiede la lezione «Introduzione a Future e Promise»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Scala for Backend Engineering & Functional Programming?
Sì. Ogni lezione Scala for Backend Engineering & Functional Programming include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Introduzione a Future e Promise
- Composizione delle operazioni asincrone
- Gestione degli errori nei Future