การประกอบการดำเนินการแบบอะซิงโครนัส
เรียนรู้การเชื่อมโยงและรวม `Futures` หลายรายการโดยใช้เมธอดอย่าง `map`, `flatMap` และนิพจน์ `for`
การประกอบการดำเนินการแบบอะซิงโครนัส เป็นบทเรียน Scala for Backend Engineering & Functional Programming ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 3 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Scala for Backend Engineering & Functional Programming และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Scala for Backend Engineering & Functional Programming มีบทเรียนทั้งหมด 3 บทเรียน
เหตุใดจึงต้องเชื่อมโยงการทำงานแบบอะซิงโครนัส
Future ช่วยให้เราเรียกใช้งานต่าง ๆ ได้โดยไม่บล็อกโปรแกรมหลัก แต่หากต้องใช้ผลลัพธ์ของงานหนึ่งกับอีกงานหนึ่ง หรือจำเป็นต้องรวมผลลัพธ์จากหลายงานเข้าด้วยกัน จะทำอย่างไรดีครับ
การประกอบ Future เข้าด้วยกันมีประโยชน์ในกรณีนี้ เราจะเรียนรู้วิธีเชื่อมโยงและรวมการทำงานแบบอะซิงโครนัสเหล่านี้ เพื่อให้โค้ด Scala ของคุณมีประสิทธิภาพและตอบสนองได้ดียิ่งขึ้น
`map`: แปลงผลลัพธ์ของ Future
เมธอด map ใช้เมื่อคุณมี Future และต้องการแปลงผลลัพธ์ที่สำเร็จแล้วเป็นค่าอื่น ฟังก์ชันแปลงค่าที่คุณระบุจะถูกนำไปใช้เมื่อ Future ทำงานเสร็จสมบูรณ์
- เมธอดนี้จะคืนค่าเป็น
Futureใหม่เสมอ - เหมาะอย่างยิ่งสำหรับการแปลงผลลัพธ์แบบง่าย ๆ ที่ทำงานพร้อมกันทันที
การใช้งาน `map` (โค้ด)
ในตัวอย่างนี้ เรารับตัวเลขจาก Future แล้วคูณตัวเลขนั้นด้วยสองโดยใช้ map การแปลงค่าจะเกิดขึ้นหลังจาก Future เริ่มต้นทำงานเสร็จแล้วเท่านั้น
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`: เชื่อมโยง Future
บางครั้งผลลัพธ์ที่สำเร็จของ Future หนึ่งรายการต้องถูกนำไปเริ่มต้น Future อีกรายการหนึ่ง นี่คือจุดที่ flatMap มีประโยชน์ เมธอดนี้จะ "คลี่" Future ที่ห่อหุ้ม Future อีกชั้นหนึ่ง (Future[Future[T]]) ให้กลายเป็น Future[T] เพียงรายการเดียว
- ใช้เมื่อฟังก์ชันแปลงค่าของคุณคืนค่าเป็น
Future - จำเป็นสำหรับการทำงานแบบอะซิงโครนัสตามลำดับ
การใช้งาน `flatMap` (โค้ด)
เราดึงรหัสผู้ใช้ก่อน จากนั้นใช้รหัสดังกล่าวเพื่อดึงรายละเอียดผู้ใช้ แต่ละขั้นตอนเป็นการทำงานแบบอะซิงโครนัสที่คืนค่าเป็น Future และ flatMap ช่วยให้ขั้นตอนเหล่านี้ทำงานตามลำดับ
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` กับ `flatMap`: ความแตกต่างสำคัญ
ผู้เรียนมักสับสนระหว่าง map และ flatMap โปรดจำไว้ดังนี้:
map: ฟังก์ชันของคุณคืนค่าเป็นค่าทั่วไป เช่นIntหรือStringดังนั้นFuture[A].map(A => B)จะได้ผลลัพธ์เป็นFuture[B]flatMap: ฟังก์ชันของคุณคืนค่าเป็นFutureอีกตัวหนึ่ง เช่นFuture[Int]หรือFuture[String]ดังนั้นFuture[A].flatMap(A => Future[B])จะได้ผลลัพธ์เป็นFuture[B]
flatMap ใช้สำหรับเชื่อมโยงการทำงานแบบอะซิงโครนัส ส่วน map ใช้สำหรับแปลงผลลัพธ์อะซิงโครนัสแบบทำงานทันที
นิพจน์ `for`: การเชื่อมโยงอย่างกระชับ
นิพจน์ for ของ Scala มีรูปแบบไวยากรณ์ที่สะอาดตาและอ่านง่ายสำหรับเชื่อมโยงการทำงานที่ใช้ map และ flatMap นิพจน์เหล่านี้เป็นเพียงน้ำตาลทางไวยากรณ์ กล่าวคือคอมไพเลอร์จะแปลงนิพจน์เหล่านี้เป็นการเรียกใช้ map, flatMap และ filter ต่อเนื่องกัน
เมื่อมีการทำงานของ Future หลายรายการที่ขึ้นต่อกัน นิพจน์ for จะทำให้โค้ดดูเกือบเหมือนการทำงานแบบปกติ
โค้ดนิพจน์ `for`
ตัวอย่างนี้ใช้นิพจน์ for เพื่อเชื่อมโยงตรรกะการดึงรหัสผู้ใช้และรายละเอียดผู้ใช้แบบเดียวกับที่เราเห็นใน flatMap สังเกตไหมครับว่าโค้ดดูสะอาดตาขึ้นมาก
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`: รวมผลลัพธ์ที่ไม่ขึ้นต่อกัน
หากคุณมี Future สองรายการที่ไม่ขึ้นต่อกันและต้องการรวมผลลัพธ์เมื่อทั้งสองรายการทำงานเสร็จแล้ว เมธอด zip เหมาะสำหรับกรณีนี้ เมธอดนี้รับ Future อีกตัวหนึ่งและคืนค่าเป็น Future ใหม่ที่เก็บคู่ข้อมูล (Tuple) ซึ่งประกอบด้วยผลลัพธ์ที่สำเร็จของทั้งสองรายการ
Future ทั้งสองรายการจะทำงานพร้อมกัน และ zip จะรอจนกว่าทั้งสองรายการจะทำงานเสร็จ
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!")
}
}ตรวจสอบความเข้าใจอย่างรวดเร็ว: การประกอบ Future
พิจารณาข้อมูลโค้ด Scala ต่อไปนี้ ค่าท้ายสุดที่พิมพ์ออกมาจะเป็นอะไรครับ
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)
}
}ทบทวน: การเชื่อมโยงงานแบบอะซิงโครนัส
คุณได้เรียนรู้วิธีที่มีประสิทธิภาพในการประกอบ Future ของ Scala ดังนี้:
map: แปลงผลลัพธ์ที่สำเร็จของFutureเป็นค่าใหม่flatMap: เชื่อมโยงFutureสองรายการ โดยใช้ผลลัพธ์ของรายการแรกเพื่อเริ่มรายการที่สอง- นิพจน์
for: มีไวยากรณ์ที่สะอาดและดูคล้ายการทำงานแบบปกติสำหรับการเชื่อมโยงflatMapและmap zip: รวมผลลัพธ์ของFutureสองรายการที่ไม่ขึ้นต่อกันเป็นทูเพิล
เครื่องมือเหล่านี้จำเป็นอย่างยิ่งต่อการสร้างแอปพลิเคชันแบบอะซิงโครนัสใน Scala ที่ตอบสนองได้ดีและมีประสิทธิภาพ
คำถามที่พบบ่อย
บทเรียน “การประกอบการดำเนินการแบบอะซิงโครนัส” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การประกอบการดำเนินการแบบอะซิงโครนัส” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Scala for Backend Engineering & Functional Programming ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Scala for Backend Engineering & Functional Programming มีบทเรียนทั้งหมด 3 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การประกอบการดำเนินการแบบอะซิงโครนัส”
เรียนรู้การเชื่อมโยงและรวม `Futures` หลายรายการโดยใช้เมธอดอย่าง `map`, `flatMap` และนิพจน์ `for` คุณปฏิบัติ Scala for Backend Engineering & Functional Programming ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Scala for Backend Engineering & Functional Programming หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Scala for Backend Engineering & Functional Programming บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 3 บทเรียน
บทเรียน “การประกอบการดำเนินการแบบอะซิงโครนัส” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Scala for Backend Engineering & Functional Programming นี้ได้ไหม
ได้ บทเรียน Scala for Backend Engineering & Functional Programming ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- บทนำสู่ Futures และ Promises
- การประกอบการดำเนินการแบบอะซิงโครนัส
- การจัดการข้อผิดพลาดใน Futures