0Pricing
Scala for Backend Engineering & Functional Programming · บทเรียน

บทนำสู่ 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. บทนำสู่ Futures และ Promises
  2. การประกอบการดำเนินการแบบอะซิงโครนัส
  3. การจัดการข้อผิดพลาดใน Futures
← กลับไปที่ Scala for Backend Engineering & Functional Programming