บทนำสู่ Futures และ Promises
ทำความเข้าใจแนวคิดหลักของ `Future` สำหรับผลลัพธ์แบบอะซิงโครนัส และ `Promise` สำหรับทำให้ผลลัพธ์เหล่านั้นเสร็จสมบูรณ์
บทนำสู่ Futures และ Promises เป็นบทเรียน Scala for Backend Engineering & Functional Programming ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 3 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Scala for Backend Engineering & Functional Programming และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Scala for Backend Engineering & Functional Programming มีบทเรียนทั้งหมด 3 บทเรียน
โค้ดแบบอะซิงโครนัส: เหตุใดจึงสำคัญ
ในการเขียนโปรแกรม งานต่าง ๆ อาจทำงานแบบพร้อมกันตามลำดับ (ทำงานทีละงาน) หรือแบบอะซิงโครนัส (งานหนึ่งเริ่มต้นได้โดยไม่ต้องรอให้งานก่อนหน้าเสร็จสิ้น)
การเขียนโปรแกรมแบบอะซิงโครนัสมีความสำคัญอย่างยิ่งต่อการสร้างแอปพลิเคชันที่ตอบสนองได้ดีและไม่หยุดค้างระหว่างรอการดำเนินการที่ใช้เวลานาน เช่น คำขอเครือข่ายหรือการสืบค้นฐานข้อมูล
ปัญหาของการเรียกที่บล็อกการทำงาน
ลองจินตนาการว่าโปรแกรมของคุณต้องดึงข้อมูลจากอินเทอร์เน็ต หากการดำเนินการนี้เป็นแบบบล็อกการทำงาน โปรแกรมจะหยุดรอและไม่ทำสิ่งอื่นจนกว่าข้อมูลจะมาถึง
สิ่งนี้อาจทำให้ส่วนติดต่อผู้ใช้ "ค้าง" หรือทำให้แอปพลิเคชันฝั่งเซิร์ฟเวอร์ทำงานไม่มีประสิทธิภาพ เราจึงต้องมีวิธีทำงานเหล่านี้เบื้องหลังโดยไม่หยุดกระแสการทำงานหลัก
ทำความรู้จัก Scala Futures
Future ของ Scala เป็นเครื่องมือที่ทรงพลังสำหรับการเขียนโปรแกรมแบบอะซิงโครนัส โดยแทนค่าที่อาจยังไม่พร้อมใช้งานในขณะนี้ แต่จะพร้อมใช้งานในภายหลัง
- ลองนึกภาพว่าเหมือนการสั่งกาแฟ คุณจะได้รับใบเสร็จ (
Future) และสามารถทำอย่างอื่นระหว่างที่กำลังชงกาแฟได้ - เมื่อกาแฟพร้อม ใบเสร็จจะ "เสร็จสมบูรณ์" พร้อมเครื่องดื่มของคุณ (ผลลัพธ์)
สร้าง Future แรกของคุณ
คุณสามารถสร้าง Future ได้โดยห่อหุ้มการคำนวณไว้ใน Future { ... } การคำนวณนี้จะทำงานบนเธรดแยกต่างหาก
จำเป็นต้องมี ExecutionContext เพื่อจัดตารางเวลางานเหล่านี้ เพื่อความเรียบง่าย เราจะใช้บริบทส่วนกลาง
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)
}ทำความเข้าใจ ExecutionContext
ExecutionContext คือกลุ่มเธรดที่ใช้เรียกใช้การคำนวณแบบอะซิงโครนัส
- จัดการว่างานจะถูกดำเนินการอย่างไรและเมื่อใด
- สำหรับตัวอย่างสั้น ๆ มักใช้
scala.concurrent.ExecutionContext.Implicits.globalซึ่งมีกลุ่มเธรดเริ่มต้นให้ - ในแอปพลิเคชันจริง คุณอาจกำหนดค่ากลุ่มเธรดเฉพาะเพื่อควบคุมการใช้ทรัพยากรได้ดียิ่งขึ้น
จัดการผลลัพธ์ของ Future: onComplete
ใช้เมธอด onComplete เพื่อกำหนดว่าจะเกิดอะไรขึ้นเมื่อ Future ทำงานเสร็จ ไม่ว่าจะสำเร็จหรือล้มเหลว
เมธอดนี้รับฟังก์ชันที่ทำงานกับ scala.util.Try ซึ่งอาจเป็น Success(value) หรือ 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
}ตัวจัดการแบบง่าย: Success/Failure
สำหรับกรณีที่ไม่ซับซ้อน คุณสามารถใช้ onSuccess และ onFailure เพื่อจัดการเฉพาะผลลัพธ์ที่สำเร็จหรือเฉพาะข้อผิดพลาดตามลำดับ
onSuccessรับฟังก์ชันสำหรับค่าที่สำเร็จonFailureรับฟังก์ชันสำหรับข้อยกเว้น- ทั้งสองเป็นเมธอดอำนวยความสะดวกที่สร้างขึ้นบน
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
}Scala Promise คืออะไร
ขณะที่ Future เป็นตัวแทนผลลัพธ์แบบอ่านอย่างเดียว Promise เป็นคอนเทนเนอร์ที่เขียนได้เพียงครั้งเดียว ซึ่งสามารถทำให้เสร็จสมบูรณ์ด้วยค่าหรือข้อยกเว้น
- ใช้
Promiseเพื่อทำให้Futureเสร็จสมบูรณ์ - คุณสร้าง
PromiseรับFutureที่เชื่อมโยงกับมัน แล้วทำให้Promiseเสร็จสมบูรณ์เมื่อผลลัพธ์พร้อม
ทำให้ Promise เสร็จสมบูรณ์
คุณสามารถทำให้ Promise เสร็จสมบูรณ์โดยใช้เมธอด success() หรือ failure() เมื่อ Promise เสร็จสมบูรณ์แล้ว Future ที่เชื่อมโยงอยู่ก็จะเสร็จสมบูรณ์ด้วย
หากพยายามทำให้ Promise เสร็จสมบูรณ์มากกว่าหนึ่งครั้ง จะทำให้เกิดข้อผิดพลาด
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 และ Promises
โดยทั่วไป Future และ Promise จะทำงานร่วมกัน รูปแบบที่พบบ่อยคือใช้ Promise เมื่อคุณต้องการควบคุมการทำให้ Future เสร็จสมบูรณ์ด้วยตนเอง ซึ่งอาจมาจากระบบภายนอกหรือส่วนติดต่อแบบเรียกกลับรุ่นเก่า
วิธีนี้ช่วยให้คุณห่อหุ้มการดำเนินการแบบอะซิงโครนัสที่ไม่ได้อิงกับ Future ให้อยู่ในรูปแบบ Future ทำให้ใช้งานร่วมกับโค้ดที่อิงกับ 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
}ตรวจสอบความเข้าใจอย่างรวดเร็ว: Future เทียบกับ Promise
ข้อความใดต่อไปนี้อธิบายบทบาทของ Future และ Promise ใน Scala ได้อย่างถูกต้อง
สรุป: Futures และ Promises
ทำได้ดีมากครับ! ในบทเรียนนี้ คุณได้เรียนรู้พื้นฐานของการเขียนโปรแกรมแบบอะซิงโครนัสใน Scala ดังนี้:
Future: ตัวแทนผลลัพธ์ที่ยังไม่พร้อมใช้งานในทันที แต่จะพร้อมใช้งานในภายหลังPromise: ตัวเก็บข้อมูลที่เขียนได้ครั้งเดียว ใช้เพื่อทำให้Futureเสร็จสมบูรณ์ด้วยตนเองExecutionContext: จัดตารางการทำงานของงานอะซิงโครนัส- วิธีจัดการผลลัพธ์ของ
Futureโดยใช้onComplete,onSuccessและonFailure
แนวคิดเหล่านี้เป็นพื้นฐานสำหรับรูปแบบการทำงานแบบอะซิงโครนัสที่ซับซ้อนยิ่งขึ้น!
คำถามที่พบบ่อย
บทเรียน “บทนำสู่ Futures และ Promises” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “บทนำสู่ Futures และ Promises” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Scala for Backend Engineering & Functional Programming ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Scala for Backend Engineering & Functional Programming มีบทเรียนทั้งหมด 3 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “บทนำสู่ Futures และ Promises”
ทำความเข้าใจแนวคิดหลักของ `Future` สำหรับผลลัพธ์แบบอะซิงโครนัส และ `Promise` สำหรับทำให้ผลลัพธ์เหล่านั้นเสร็จสมบูรณ์ คุณปฏิบัติ Scala for Backend Engineering & Functional Programming ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Scala for Backend Engineering & Functional Programming หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Scala for Backend Engineering & Functional Programming บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 3 บทเรียน
บทเรียน “บทนำสู่ Futures และ Promises” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Scala for Backend Engineering & Functional Programming นี้ได้ไหม
ได้ บทเรียน Scala for Backend Engineering & Functional Programming ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- บทนำสู่ Futures และ Promises
- การประกอบการดำเนินการแบบอะซิงโครนัส
- การจัดการข้อผิดพลาดใน Futures