Future/Promise — คืออะไร การคำนวณแบบอะซิงโครนัสและการเขียนโปรแกรม

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-03-17 เวลาอ่าน: 9 นาที

Future/Promise คือรูปแบบการเขียนโปรแกรมแบบอะซิงโครนัสที่แสดงคอนเทนเนอร์สำหรับผลลัพธ์ของการดำเนินการที่ยังไม่เสร็จสมบูรณ์ ตาม Dart Documentation, 2025 Future คือผลลัพธ์แบบอ่านอย่างเดียวของการคำนวณที่เลื่อนออกไป Promise คือสัญญาแบบเขียนอย่างเดียวที่เติมผลลัพธ์นี้ Future ถูกใช้ใน Dart, Java, Scala และ C++ สำหรับเชน then/catch

ประเด็นสำคัญ

  • Future — คอนเทนเนอร์แบบอ่านอย่างเดียวสำหรับผลลัพธ์อะซิงโครนัสที่พร้อมใช้งานในอนาคต
  • Promise — ตัวยึดตำแหน่งแบบเขียนอย่างเดียวที่รับผลลัพธ์และส่งต่อไปยัง Future
  • เชน then — การประมวลผลตามลำดับของการดำเนินการอะซิงโครนัสโดยไม่มี callback ซ้อนกัน
  • Future ใน Dart — พื้นฐานของ async/await และไลบรารี dio, http, shelf
  • Future/Promise — ทางเลือกรูปแบบ callback และพื้นฐานสำหรับไวยากรณ์ async/await

Future/Promise คืออะไร?

Future/Promise คือคู่ของอ็อบเจกต์ที่เชื่อมโยงกันซึ่งแบ่งผลลัพธ์อะซิงโครนัสออกเป็นสองบทบาท Promise สามารถเขียนผลลัพธ์ (resolve) หรือข้อผิดพลาด (reject) Future สามารถอ่านได้อย่างเดียว — ผ่าน callback (then, catchError) หรือผ่าน await การแยกนี้รับประกันว่าผู้บริโภคไม่สามารถเปลี่ยนแปลงผลลัพธ์ได้ มีเพียงใช้งานเท่านั้น

Future ใน Dart

ภาษา Dart ใช้ Future เป็นกลไกอะซิงโครนัสหลัก Future<T> คือสัญญาที่จะรับค่าชนิด T ในอนาคต Future สามารถอยู่ในหนึ่งในสามสถานะ: unresolved (การดำเนินการกำลังดำเนินการ), resolved with value (เสร็จสมบูรณ์สำเร็จ) หรือ resolved with error (เสร็จสมบูรณ์ด้วยข้อผิดพลาด) เมื่อเปลี่ยนเป็นสถานะ resolved แล้ว Future จะไม่เปลี่ยนแปลงอีก

Promise ใน JavaScript

Promise ใน JavaScript คล้ายกับ Future ของ Dart แต่มี API ที่สมบูรณ์กว่า Promise รับ executor — ฟังก์ชันที่มีพารามิเตอร์ resolve และ reject เมธอดแบบสแตติก Promise.all, Promise.race, Promise.allSettled อนุญาตให้รวม promises หลายตัว แอปพลิเคชันสมัยใหม่ใช้ไวยากรณ์ async/await บน Promise

Future ทำงานอย่างไร

Future ทำงานบนพื้นฐานของ event loop — วงจรเหตุการณ์ที่ประมวลผลการดำเนินการอะซิงโครนัสโดยไม่บล็อกเธรดหลัก เมื่อฟังก์ชันอะซิงโครนัสถูกเรียก (เช่น http.get) ฟังก์ชันจะคืนค่า Future ทันที คำขอจริงทำงานในเบื้องหลัง ในขณะที่ event loop ยังคงประมวลผลเหตุการณ์อื่นๆ ต่อไป หลังจากการดำเนินการเสร็จสมบูรณ์ Future จะเปลี่ยนเป็นสถานะ resolved และ then จะถูกเรียก

Event loop คือกลไกสำคัญที่ Dart และ JavaScript สร้างขึ้น Event loop รักษาคิวสองคิว: คิว microtask (งานสั้น ดำเนินการก่อนเหตุการณ์ถัดไป) และคิวเหตุการณ์ (เหตุการณ์ IO, ตัวจับเวลา) Future.then วาง callback ในคิว microtask, Future.microtask — ดำเนินการสำคัญก่อนเฟรมถัดไป

เชนของ then() อนุญาตให้ประมวลผลผลลัพธ์ของการดำเนินการอะซิงโครนัสตามลำดับโดยไม่มี callback hell แต่ละ then() รับผลลัพธ์ของขั้นตอนก่อนหน้าและคืนค่า Future ใหม่ catchError() ที่จุดสิ้นสุดของเชนจัดการข้อผิดพลาดใดๆ ที่เกิดขึ้นในขั้นตอนใดๆ ทำให้โค้ดอะซิงโครนัสเป็นเชิงเส้นและอ่านง่าย

CompletableFuture ใน Java

ใน Java CompletableFuture ขยายแนวคิด Future/Promise เมธอด supplyAsync() เริ่มงานอะซิงโครนัสใน ForkJoinPool.commonPool() thenApply() แปลงผลลัพธ์ thenCompose() เปิด CompletableFuture ที่ซ้อนกัน exceptionally() จัดการข้อผิดพลาดโดยคืนค่าเริ่มต้น allOf() และ anyOf() ทำงานเหมือน Promise.all และ Promise.race ใน JavaScript CompletableFuture รองรับการเสร็จสมบูรณ์ด้วยตนเองผ่าน complete() และ completeExceptionally() — ซึ่งคล้ายกับ Promise resolve/reject

Promise และสัญญาอะซิงโครนัส

Promise คือสัญญาที่มีหนึ่งในสามสถานะ: pending (รอดำเนินการ), fulfilled (สำเร็จ) หรือ rejected (ถูกปฏิเสธ) เมื่อเปลี่ยนเป็น fulfilled หรือ rejected แล้ว Promise จะไม่เปลี่ยนแปลงอีก — ซึ่งรับประกันความไม่แปรเปลี่ยนของผลลัพธ์สำหรับผู้บริโภคทั้งหมด เมธอด .then() จะถูกเรียกแบบอะซิงโครนัสหลังจากเปลี่ยนเป็นสถานะที่เสร็จสมบูรณ์ใดๆ

Promise.all รอให้ promises ทั้งหมดที่ส่งเข้ามาเสร็จสมบูรณ์และคืนค่าอาเรย์ของผลลัพธ์ในลำดับเดียวกัน หาก promise หนึ่งล้มเหลวด้วยข้อผิดพลาด — Promise.all ทั้งหมดจะเปลี่ยนเป็น rejected Promise.race คืนค่าผลลัพธ์ของ promise ที่เสร็จสมบูรณ์ตัวแรก (สำเร็จหรือข้อผิดพลาด) Promise.allSettled รอ promises ทั้งหมดโดยไม่คำนึงถึงข้อผิดพลาด — คืนค่าสถานะของแต่ละตัว

การเชน คือข้อได้เปรียบสำคัญของ Promise เหนือ callback แต่ละ .then() คืนค่า Promise ใหม่ ทำให้สามารถสร้างเชนที่มีความยาวตามต้องการ ข้อผิดพลาดในจุดใดๆ ของเชนจะถูกส่งต่อไปยัง .catch() ที่ใกล้ที่สุด เมธอด finally() ดำเนินการโค้ดหลังจากเชนเสร็จสมบูรณ์โดยไม่คำนึงถึงผลลัพธ์ — สำหรับการทำความสะอาดทรัพยากร

ตัวอย่างโค้ด Future (Dart)

ตัวอย่างแรก — การสร้าง Future ผ่านฟังก์ชัน async และจัดการด้วย then/catchError:

dart
Future<String> fetchData() async {
    await Future.delayed(Duration(seconds: 1))
    return "โหลดข้อมูลแล้ว"
}

fetchData()
    .then((result) => print(result))
    .catchError((error) => print("ข้อผิดพลาด: $error"))

ตัวอย่างที่สอง — การรวม Futures หลายตัวด้วย Future.wait:

dart
Future<List<String>> loadAll() async {
    final futures = [
        fetchFromApi("/users"),
        fetchFromApi("/posts"),
        fetchFromApi("/comments")
    ]
    final results = await Future.wait(futures)
    return results
}

ตัวอย่างที่สาม — Promise ใน JavaScript ด้วยการสร้างด้วยตนเองและเชน then:

js
const promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve("เสร็จแล้ว")
    }, 1000)
})

promise
    .then(value => console.log(value))
    .catch(err => console.error(err))

Future เทียบกับรูปแบบอะซิงโครนัสอื่นๆ

Future/Promise แตกต่างจากสไตล์ callback ตรงที่คืนค่าอ็อบเจกต์สัญญาแทนที่จะรับฟังก์ชัน callback เป็นอาร์กิวเมนต์ สไตล์ callback นำไปสู่การซ้อนกัน (callback hell) ในขณะที่ Future อนุญาตให้สร้างเชน then() แบบราบ ไวยากรณ์ async/awat ทำให้โค้ด Future เป็นเชิงเส้นมากขึ้น คล้ายกับโค้ดซิงโครนัส

Future แทนผลลัพธ์อะซิงโครนัสหนึ่งตัวพอดี — การปล่อยหนึ่งครั้ง หลังจากนั้น Future จะเสร็จสมบูรณ์ แตกต่างจาก Observable (Rx, ReactiveX) หรือ Flow (Kotlin Coroutines) ตรงที่ Future ไม่รองรับค่าหลายค่าเมื่อเวลาผ่านไป หากคุณต้องการสตรีมเหตุการณ์ — ใช้ Stream ใน Dart, Observable ใน Rx หรือ Flow ใน Kotlin

CompletableFuture ใน Java เป็นอะนาล็อกของ Promise ที่มี API ขยาย: supplyAsync, thenApply, thenCompose, exceptionally CompletableFuture อนุญาตให้รวมการดำเนินการอะซิงโครนัสหลายตัวผ่าน allOf, anyOf และยังอนุญาตให้ระบุ Executor ที่กำหนดเองสำหรับการดำเนินการ Scala Future ใช้ ExecutionContext เพื่อจัดการพูลเธรดและรองรับการประกอบผ่าน for-comprehension

ใน Dart รูปแบบ Future แตกต่างจาก Promise ใน JavaScript ตรงที่ Dart มีการกำหนดชนิดที่เข้มงวด: Future<String> รับประกันชนิดของค่าที่ส่งคืน ฟังก์ชัน async ใน Dart ต้องคืนค่า Future และคอมไพเลอร์จะตรวจสอบว่าเส้นทางทั้งหมดคืนค่าชนิดที่ถูกต้อง Future.wait เทียบเท่ากับ Promise.all — รับ Iterable<Future<T>> และคืนค่า Future<List<T>> Future.delayed และ Future.error เป็นโรงงานที่สะดวกสำหรับการทดสอบสถานการณ์อะซิงโครนัส

Future/Promise ถูกนำไปใช้ใน Python ผ่าน concurrent.futures.Future และ asyncio.Future concurrent.futures.ThreadPoolExecutor.submit() คืนค่า Future ซึ่งสามารถเรียก result() ได้ — การเรียกแบบบล็อก asyncio.Future เป็นคอนเทนเนอร์ที่เข้ากันได้กับ await สำหรับผลลัพธ์อะซิงโครนัสใน Asyncio asyncio.gather() ทำงาน coroutines หลายตัวพร้อมกันและคืนค่ารายการผลลัพธ์ คล้ายกับ Promise.all ใน JavaScript Python ยังใช้ asyncio.ensure_future ที่ใช้ callback และเชน add_done_callback สำหรับประกอบการดำเนินการอะซิงโครนัส แต่ในโค้ดสมัยใหม่ ไวยากรณ์ async/await กับ asyncio.Task เป็นที่นิยมกว่า

ในการพัฒนามือถือ Future ถูกใช้อย่างแข็งขันในแอปพลิเคชัน Flutter ทุกคำขอเครือข่ายจากแพ็กเกจ http หรือ dio คืนค่า Future FutureBuilder คือวิดเจ็ตที่รับ Future และสถานะ snapshot: connectionDone, hasData, hasError เมื่อได้รับข้อมูล snapshot.data จะมีผลลัพธ์ของ Future StreamBuilder เป็นอะนาล็อกสำหรับค่าหลายตัว FutureBuilder ขจัดการจัดการสถานะการโหลดด้วยตนเองผ่าน setState

Scala Future ใช้ ExecutionContext โดยปริยาย — พูลเธรดที่งานอะซิงโครนัสดำเนินการ การประกอบผ่าน map, flatMap, filter ทำงานเนื่องจาก Future เป็นโมแนด for-comprehension อนุญาตให้รวม Futures หลายตัวตามลำดับโดยไม่ซ้อนกัน: for { a <- futureA; b <- futureB } yield a + b Future.sequence ทำงานเหมือน Promise.all การตกกลับข้อผิดพลาดถูกนำไปใช้ผ่าน recover และ recoverWith

Future/Promise ใน C++ แสดงโดยคลาส std::future และ std::promise จากไลบรารี <future> std::async เริ่มฟังก์ชันอะซิงโครนัสและคืนค่า std::future std::promise อนุญาตให้ตั้งค่าด้วยตนเองผ่าน set_value() หรือข้อผิดพลาดผ่าน set_exception() แตกต่างจาก Dart และ JavaScript std::future.get() บล็อกเธรดจนกว่าจะได้รับผลลัพธ์ — นี่คือความแตกต่างสำคัญที่ต้องพิจารณาเมื่อออกแบบแอปพลิเคชัน C++ แบบหลายเธรด

รูปแบบ Future

เมื่อออกแบบ API ที่คืนค่า Future ให้ปฏิบัติตามกฎ แหล่งความจริงเดียว: คำขออะซิงโครนัสแต่ละครั้งถูกสร้างขึ้นครั้งเดียวและแคชผ่าน Future.memoize หากสองคอมโพเนนต์ขอข้อมูลเดียวกัน พวกเขาจะได้รับ Future เดียวกัน — ซึ่งป้องกันคำขอซ้ำ สำหรับ timeout ให้ใช้ Future.timeout (Dart) หรือ Promise.race พร้อมกับ timeout เพื่อรับประกันว่าการดำเนินการอะซิงโครนัสจะเสร็จสมบูรณ์ภายในช่วงเวลาที่กำหนด

รูปแบบลองใหม่ ใน Future ถูกนำไปใช้ผ่านเชนแบบเรียกซ้ำ: เมื่อข้อผิดพลาดใน catch ฟังก์ชันอะซิงโครนัสเดียวกันจะถูกเรียกด้วยความล่าช้า Exponential backoff เพิ่มช่วงเวลาระหว่างความพยายาม: 1 วินาที — 2 วินาที — 4 วินาที — สูงสุด 30 วินาที ใน Dart สิ่งนี้ถูกห่อหุ้มในส่วนขยายบน Future: future.retry(maxRetries: 3, delay: Duration(seconds: 1)) ใน Scala Future.zip รวมผลลัพธ์อิสระสองตัวเป็นทูเพิล — ทางเลือกสำหรับ Promise.all สำหรับสอง Future การยกเลิกไม่ได้รับการสนับสนุนใน Future มาตรฐาน แต่ถูกนำไปใช้ผ่าน CancellationToken หรือ AbortController ใน JavaScript

คำถามที่พบบ่อย

ความแตกต่างระหว่าง Future และ Promise คืออะไร?

Future คือคอนเทนเนอร์แบบอ่านอย่างเดียวสำหรับอ่านผลลัพธ์อะซิงโครนัสผ่าน then หรือ await Promise คือสัญญาแบบเขียนอย่างเดียวที่รับค่าผ่าน resolve() และเชื่อมโยงกับ Future ใน Dart และ JavaScript แนวคิดเหล่านี้รวมกัน: Future/Promise เป็นคลาสเดียวกัน ใน Java และ Scala แยกกัน

Future แตกต่างจาก Observable อย่างไร?

Future แทนผลลัพธ์อะซิงโครนัสเดียว — มันปล่อยค่าหนึ่งค่าและเสร็จสมบูรณ์ Observable (Rx) ปล่อยหลายค่าเมื่อเวลาผ่านไป — มันคือสตรีมอะซิงโครนัส หากคุณต้องการการตอบสนอง HTTP หนึ่งครั้ง — ใช้ Future หากคุณต้องการสตรีมการเปลี่ยนแปลงฐานข้อมูล — ใช้ Observable หรือ Stream

async/await คืออะไรและเกี่ยวข้องกับ Future อย่างไร?

async/await คือน้ำตาลทางไวยากรณ์เหนือ Future/Promise คีย์เวิร์ด async ทำเครื่องหมายฟังก์ชันเป็นอะซิงโครนัส — มันคืนค่า Future await หยุดการทำงานชั่วคราวจนกว่า Future จะเสร็จสมบูรณ์ โดยไม่บล็อกเธรด ใน Dart, JavaScript, Python และ C# async/await ได้แทนที่เชน then ในสถานการณ์ส่วนใหญ่

วิธีการจัดการข้อผิดพลาดในเชน Future?

ใน Dart ใช้ .catchError() ที่จุดสิ้นสุดของเชน — มันจับข้อยกเว้นในขั้นตอนใดๆ ใน JavaScript — .catch() Dart ยังมี try/await/catch ภายในฟังก์ชัน async สำหรับการกู้คืนข้อผิดพลาด ให้ใช้ .catchError() พร้อมกับการคืนค่าเริ่มต้นหรือ Future ใหม่

Promise.all คืออะไรและใช้เมื่อใด?

Promise.all รับอาเรย์ของ promises และคืนค่า Promise เดียวที่แก้ปัญหาด้วยอาเรย์ของผลลัพธ์ promises ทั้งหมดทำงานพร้อมกัน — ซึ่งเร่งการดำเนินการอิสระ (เช่น การโหลดหลายไฟล์) หาก promise ใดถูกปฏิเสธ — Promise.all ทั้งหมดจะถูกปฏิเสธด้วยข้อผิดพลาดเดียวกัน

สรุป

  • Future/Promise — รูปแบบการเขียนโปรแกรมอะซิงโครนัสที่มีสัญญาสำหรับค่าเดียว
  • Future — คอนเทนเนอร์แบบอ่านอย่างเดียวสำหรับอ่านผลลัพธ์การดำเนินการ
  • Promise — สัญญาแบบเขียนอย่างเดียวที่เติม Future ผ่าน resolve/reject
  • เชน then — การประมวลผลแบบราบของขั้นตอนอะซิงโครนัสโดยไม่มี callback hell
  • async/await — น้ำตาลทางไวยากรณ์เหนือ Future ทำให้โค้ดเป็นเชิงเส้น
  • Promise.all — การดำเนินการพร้อมกันของการดำเนินการอะซิงโครนัสหลายตัว
  • สำหรับค่าหลายตัวเมื่อเวลาผ่านไป ให้ใช้ Stream หรือ Observable ไม่ใช่ Future

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม