Composizione delle operazioni asincrone
Impari a concatenare e combinare più `Future` utilizzando metodi come `map`, `flatMap` e le comprensioni `for`.
Composizione delle operazioni asincrone è una lezione Scala for Backend Engineering & Functional Programming gratuita su CoddyKit. Questa è la lezione 2 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.
Perché concatenare le operazioni asincrone?
I Future consentono di eseguire attività senza bloccare il programma principale. Ma cosa succede se il risultato di un'attività è necessario per un'altra, oppure se occorre combinare i risultati di più attività?
È qui che la composizione dei Future si rivela utile. Si imparerà a concatenare e combinare queste operazioni asincrone, rendendo il codice Scala più potente e reattivo.
`map`: trasformare il risultato di un Future
Il metodo map si usa quando si dispone di un Future e si vuole trasformare il suo risultato positivo in un altro valore. La funzione di trasformazione fornita verrà applicata quando il Future sarà completato correttamente.
- Restituisce sempre un nuovo
Future. - È ideale per semplici trasformazioni sincrone su un risultato asincrono.
`map` in azione (codice)
In questo caso si ottiene un numero da un Future e lo si raddoppia usando map. La trasformazione avviene solo dopo il completamento del Future iniziale.
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`: concatenare i Future
A volte il risultato positivo di un Future deve avviare un altro Future. È qui che flatMap dà il meglio di sé. "Appiattisce" un Future di un Future (Future[Future[T]]) trasformandolo in un singolo Future[T].
- Usarlo quando la funzione di trasformazione restituisce un
Future. - È essenziale per le operazioni asincrone sequenziali.
`flatMap` in azione (codice)
Si recupera un ID utente, quindi si usa quell'ID per recuperare i dettagli dell'utente. Ogni passaggio è un'operazione asincrona che restituisce un Future. flatMap garantisce che vengano eseguiti in sequenza.
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` e `flatMap`: differenza fondamentale
È comune confondere map e flatMap. Occorre ricordare:
map: la funzione restituisce un valore normale (ad esempioInt,String).Future[A].map(A => B)produceFuture[B].flatMap: la funzione restituisce un altroFuture(ad esempioFuture[Int],Future[String]).Future[A].flatMap(A => Future[B])produceFuture[B].
flatMap serve per concatenare operazioni asincrone, mentre map serve per trasformare sincronicamente un risultato asincrono.
Comprehension `for`: concatenazione elegante
Le comprehension for di Scala offrono una sintassi chiara e leggibile per concatenare operazioni che coinvolgono map e flatMap. Sono esclusivamente zucchero sintattico, cioè il compilatore le traduce in una serie di chiamate a map, flatMap e filter.
Quando si hanno più operazioni Future dipendenti tra loro, le comprehension for fanno apparire il codice quasi sincrono.
Codice di una comprehension `for`
Questo esempio usa una comprehension for per concatenare la stessa logica di recupero dell'ID utente e dei relativi dettagli già vista con flatMap. Si noti quanto risulti più pulito!
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`: combinare risultati indipendenti
Cosa succede se si hanno due indipendenti Future e si vogliono combinare i relativi risultati quando entrambi sono completati? Il metodo zip è perfetto a questo scopo. Prende un altro Future e restituisce un nuovo Future contenente una coppia (una Tuple) dei rispettivi risultati positivi.
Entrambi i future vengono eseguiti in concorrenza e zip attende che entrambi terminino.
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 rapida: composizione dei Future
Si consideri il seguente frammento di codice Scala. Quale sarà l'ultimo valore stampato?
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)
}
}Riepilogo: concatenare attività asincrone
Sono stati appresi metodi potenti per comporre i Future di Scala:
map: trasforma il risultato positivo di unFuturein un nuovo valore.flatMap: concatena dueFuture, usando il risultato del primo per avviare il secondo.- comprehension
for: offrono una sintassi chiara, simile a quella sincrona, per concatenareflatMapemap. zip: combina i risultati di dueFutureindipendenti in una tupla.
Questi strumenti sono fondamentali per creare applicazioni asincrone reattive ed efficienti in Scala!
Domande Frequenti
La lezione «Composizione delle operazioni asincrone» è gratuita?
Sì — il testo completo di «Composizione delle operazioni asincrone» è 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 «Composizione delle operazioni asincrone»?
Impari a concatenare e combinare più `Future` utilizzando metodi come `map`, `flatMap` e le comprensioni `for`. 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 2 di 3.
Quanto tempo richiede la lezione «Composizione delle operazioni asincrone»?
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