Scala för backendutveckling och funktionell programmering · Lektion

Sammansättning av asynkrona operationer

Lär er att kedja och kombinera flera `Futures` med metoder som `map`, `flatMap` och `for`-komprehensioner.

Lektion 2 av 311 steg

Sammansättning av asynkrona operationer är en gratis lektion i Scala för backendutveckling och funktionell programmering på CoddyKit. Detta är lektion 2 av 3. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Scala för backendutveckling och funktionell programmering, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Scala för backendutveckling och funktionell programmering innehåller totalt 3 lektioner.

Varför kedja asynkrona operationer?

Futures hjälper oss att köra uppgifter utan att blockera huvudprogrammet. Men vad händer om resultatet från en uppgift behövs av en annan, eller om vi behöver kombinera resultat från flera uppgifter?

Det är här komposition av Futures kommer till nytta. Ni kommer att lära Er att kedja och kombinera dessa asynkrona operationer, så att Er Scala-kod blir kraftfullare och mer responsiv.

`map`: Omvandla resultatet från en Future

Metoden map används när Ni har en Future och vill omvandla dess lyckade resultat till ett annat värde. Omvandlingsfunktionen som Ni anger tillämpas när Future har slutförts utan fel.

  • Den returnerar alltid en ny Future.
  • Den passar perfekt för enkla, synkrona omvandlingar av ett asynkront resultat.

`map` i praktiken (kod)

Här hämtar vi ett tal från en Future och dubblar det sedan med hjälp av map. Omvandlingen sker först när den ursprungliga Future har slutförts.

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

Ibland behöver det lyckade resultatet från en Future starta en annan Future. Det är här flatMap kommer till sin rätt. Den "plattar ut" en Future av en Future (Future[Future[T]]) till en enda Future[T].

  • Använd den när omvandlingsfunktionen returnerar en Future.
  • Den är oumbärlig för sekventiella asynkrona operationer.

`flatMap` i praktiken (kod)

Vi hämtar ett användar-ID och använder sedan detta ID för att hämta användaruppgifter. Varje steg är en asynkron operation som returnerar en Future. flatMap säkerställer att de körs i följd.

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` jämfört med `flatMap`: Viktig skillnad

Det är vanligt att blanda ihop map och flatMap. Kom ihåg:

  • map: Er funktion returnerar ett vanligt värde (till exempel Int eller String). Future[A].map(A => B) resulterar i Future[B].
  • flatMap: Er funktion returnerar en annan Future (till exempel Future[Int] eller Future[String]). Future[A].flatMap(A => Future[B]) resulterar i Future[B].

flatMap används för att kedja asynkrona operationer, medan map används för att omvandla ett asynkront resultat synkront.

`for`-comprehensions: Elegant kedjning

Scalas for-comprehensions erbjuder en ren och lättläst syntax för att kedja operationer som innefattar map och flatMap. De är enbart syntaktiskt socker, vilket innebär att kompilatorn översätter dem till en serie anrop till map, flatMap och filter.

När Ni har flera beroende Future-operationer får koden med for-comprehensions ett nästan synkront utseende.

Kod med en `for`-comprehension

Det här exemplet använder en for-comprehension för att kedja samma logik för hämtning av användar-ID och användaruppgifter som vi såg med flatMap. Lägg märke till hur mycket renare det ser ut!

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`: Kombinera oberoende resultat

Vad gör Ni om Ni har två oberoende Futures och vill kombinera deras resultat när båda har slutförts? Metoden zip passar perfekt för detta. Den tar emot en annan Future och returnerar en ny Future som innehåller ett par (en Tuple) av deras lyckade resultat.

Båda futures körs samtidigt, och zip väntar på att båda ska slutföras.

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

Snabb kontroll: Komposition av Futures

Betrakta följande Scala-kod. Vilket slutligt värde kommer att skrivas ut?

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

Sammanfattning: Kedja asynkrona uppgifter

Ni har lärt Er kraftfulla sätt att komponera Scala-Futures:

  • map: Omvandlar en Futures lyckade resultat till ett nytt värde.
  • flatMap: Kedjar två Futures där resultatet från den första används för att starta den andra.
  • for-comprehensions: Ger en ren syntax med synkront utseende för kedjor av flatMap och map.
  • zip: Kombinerar resultaten från två oberoende Futures till en tupel.

Dessa verktyg är avgörande för att bygga responsiva och effektiva asynkrona applikationer i Scala!

Gratis att börja

Lär dig Scala med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
39
Lektioner
143

Vanliga frågor

Är lektionen ”Sammansättning av asynkrona operationer” gratis?

Ja – hela texten till ”Sammansättning av asynkrona operationer” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Scala för backendutveckling och funktionell programmering, kan Ni uppgradera till CoddyKit PRO. Kursen i Scala för backendutveckling och funktionell programmering innehåller totalt 3 lektioner.

Vad lär jag mig i ”Sammansättning av asynkrona operationer”?

Lär er att kedja och kombinera flera `Futures` med metoder som `map`, `flatMap` och `for`-komprehensioner. Ni övar på Scala för backendutveckling och funktionell programmering med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Scala för backendutveckling och funktionell programmering?

Du behöver inga förkunskaper. Utbildningen i Scala för backendutveckling och funktionell programmering på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 2 av 3.

Hur lång tid tar lektionen ”Sammansättning av asynkrona operationer”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Scala för backendutveckling och funktionell programmering-lektionen?

Ja. Varje Scala för backendutveckling och funktionell programmering-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Introduktion till Futures och Promises
  2. Sammansättning av asynkrona operationer
  3. Felhantering i Futures
← Tillbaka till Scala för backendutveckling och funktionell programmering