Promise เป็นกล่องใส่ของที่อาจยังไม่มาถึง
สร้างกล่องปุ๊บ ยังไม่ต้องมีของข้างในทันที — ของจะมาเมื่อ async operation เสร็จ
JavaScript Phase Overview
ภาพรวมของ `Promises` series — เข้าใจว่า Promise คืออะไร แก้ปัญหาอะไร ใช้เมื่อไรในงานจริง ภาพจำสำคัญ 4 ข้อ ข้อควรระวังที่พบบ่อย และเส้นทางการเรียนรู้ 5 บทลูก
`Promise` เป็น object ใน JavaScript ที่ใช้ **แทนค่าที่ยังไม่พร้อมใช้ในตอนนี้ แต่จะพร้อมในอนาคต** — เหมือน "สัญญาว่าจะส่งค่ามาให้เมื่อทำงานเสร็จ" แทนที่จะรอผลลัพธ์แบบ blocking (หยุดทุกอย่างจนกว่าจะเสร็จ) Promise บอกว่า "ฉันจะทำงานนี้ให้ แล้วเดี๋ยวค่อยแจ้งผล" — ทำให้โค้ดส่วนอื่นทำงานต่อไปได้ระหว่างรอ Promise มี 3 สถานะสำคัญ: • **pending** — งานยังไม่เสร็จ ยังไม่รู้ผล • **fulfilled** — งานสำเร็จ ได้ค่ากลับมา • **rejected** — งานล้มเหลว มี error เกิดขึ้น ตัวอย่างด้านล่างแสดงให้เห็นว่า Promise ทำงานแบบ async — โค้ดที่อยู่ถัดจาก `.then()` รันทันที ไม่ต้องรอ
const promise = Promise.resolve("สวัสดี");
console.log("1. ก่อน .then()");
promise.then((value) => {
console.log("3. ใน .then() — ได้ค่า:", value);
});
console.log("2. หลัง .then()");
// ลำดับใน console:
// "1. ก่อน .then()" ← sync, รันทันที
// "2. หลัง .then()" ← sync, รันทันที
// "3. ใน .then() — ได้ค่า: สวัสดี" ← async, รันทีหลังก่อนมี Promise การเขียน asynchronous code ใน JavaScript มักใช้ **callback nesting** — ส่ง callback ซ้อน callback เป็นชั้น ๆ จนโค้ดอ่านยากมากและจัดการ error ได้ลำบาก เราเรียกปัญหานี้ว่า `callback hell` Promise แก้ปัญหานี้ด้วยการ **ต่อขั้นตอนเป็น chain** — เขียนจากบนลงล่าง อ่านง่าย และมีระบบจัดการ error ในตัว
// ❌ callback nesting — อ่านจากในออกนอก สับสนง่าย
loadUser((user) => {
loadOrders(user.id, (orders) => {
loadDetails(orders[0].id, (details) => {
console.log(details);
});
});
});
// ✅ Promise chain — อ่านจากบนลงล่าง ต่อกันเป็นเส้นตรง
loadUser()
.then((user) => loadOrders(user.id))
.then((orders) => loadDetails(orders[0].id))
.then((details) => console.log(details));Promise ไม่ได้ถูกใช้แค่ตอนเรียก API — มันเป็น pattern หลักของ JavaScript สำหรับจัดการงานใดก็ตามที่ **ใช้เวลาและไม่อยากให้บล็อก execution อื่น** ตารางด้านล่างช่วยให้เห็นว่าแต่ละสถานการณ์ในงานจริงเชื่อมโยงกับส่วนไหนของ Promise API
| สถานการณ์ | Promise API ที่ใช้ | ตัวอย่าง |
|---|---|---|
| เรียก API หรือรอข้อมูลจาก server | `.then()` + `.catch()` | `fetch()`, axios, database query |
| ทำงานหลายขั้นตอนต่อกันตามลำดับ | `.then()` chain | login → get profile → get notifications |
| ดัก error และกู้คืนด้วยค่า default | `.catch()` recovery | API ล้ม → ใช้ cached data แทน |
| cleanup หลังงานเสร็จ ไม่ว่าสำเร็จหรือล้ม | `.finally()` | ปิด loading spinner, ล้าง connection |
| รอหลายงานพร้อมกัน โดยไม่ต้องรอทีละงาน | `Promise.all()` | โหลด product, review, related items พร้อมกัน |
ภาพที่สำคัญที่สุดของหัวข้อ Promise คือแยก 4 เรื่องออกจากกันให้ได้: 1. **Promise เป็นกล่อง** — ข้างในอาจยังไม่มีค่าหรือมีแล้วก็ได้ 2. **Promise object กับค่าข้างในไม่ใช่สิ่งเดียวกัน** — ต้องใช้ `.then()` ถึงจะเอาค่าออกมา 3. **`.then()` chain = pipeline แบน** — ไม่ใช่การซ้อน callback แบบพีระมิด 4. **Error ไหลตาม chain อัตโนมัติ** — `.catch()` ท้าย chain จับ error จากทุกขั้นก่อนหน้า ถ้าจำ 4 เรื่องนี้ได้ การเรียนบทลูกจะง่ายขึ้นมาก
จำ 4 ข้อนี้ได้ก่อนลงบทลูก เรื่อง Promise จะเป็นระบบขึ้นมาก
สร้างกล่องปุ๊บ ยังไม่ต้องมีของข้างในทันที — ของจะมาเมื่อ async operation เสร็จ
`const p = Promise.resolve(42); console.log(p)` ไม่ได้ `42` — ต้อง `p.then(v => console.log(v))`
`.then()` ทุกตัวคืนค่า Promise ตัวใหม่ — ทำให้ต่อกันเป็นเส้นตรง อ่านจากบนลงล่าง
`.catch()` ท้าย chain ดัก error จากทุก `.then()` ก่อนหน้า — ไม่ต้องใส่ error handler ทุกขั้น
Promise เป็นหัวข้อที่ใช้ได้จริงมาก แต่ก็เป็นหัวข้อที่มีจุดพลาดซ้ำ ๆ เยอะเช่นกัน หน้านี้ยังไม่ลงลึกวิธีแก้ทุกข้อ เป้าหมายคือให้คุณจำชื่อของปัญหาเหล่านี้ให้ได้ก่อน เพื่อจะไม่ตกใจเมื่อเจอในบทถัดไปหรือในงานจริง
รู้จักไว้ก่อน แล้วค่อยไปเก็บรายละเอียดและตัวอย่างเต็มในแต่ละบทลูก
`.then(() => { fetchData() })` กับ `.then(() => fetchData())` ให้ผลไม่เหมือนกัน — ถ้าไม่มี `return` ตัวถัดไปได้รับ `undefined`
Promise ที่ reject โดยไม่มี `.catch()` จะกลายเป็น `UnhandledPromiseRejection` — ทำให้ดีบักยากและอาจทำให้โปรแกรมหยุด
`new Promise(...)` หรือ `fetch()` ที่ไม่ได้ต่อด้วย `.then()` หรือ `.catch()` — โค้ดรันต่อทันทีโดยไม่รู้ว่า success หรือ fail
`fetch()` คืนค่า Promise อยู่แล้ว — ไม่ต้องห่อด้วย `new Promise()` อีกชั้น (constructor anti-pattern)
มองภาพรวมแบบง่ายที่สุดคือ Promise มี **2 บทบาทหลัก**: บทบาท **ผู้บริโภค** (ใช้ `.then()`, `.catch()`, `.finally()` กับ Promise ที่มีคนสร้างให้) และบทบาท **ผู้สร้าง** (ใช้ `new Promise()` หรือ wrapper function คืนค่า Promise) — ถ้าแยกสองบทบาทนี้ออกได้ จะสับสนน้อยลงมาก
รอบนี้เราแยก `Promises` ออกมาเป็น phase หลักของตัวเอง — 5 บทลูกเรียงลำดับจากพื้นฐานไปสู่การใช้งานจริง แต่ละหน้ามีทั้งเนื้อหาอ่านและแบบฝึกให้ลอง ถ้ายังใหม่กับ Promise แนะนำให้เริ่มจาก `Promise Basics` และไล่ไปตามลำดับ เพราะแต่ละบทต่อยอดจากบทก่อนหน้าโดยตรง
| ถ้าโจทย์ของคุณเป็นแบบนี้ | ควรไปบทไหน |
|---|---|
| อยากเข้าใจว่า Promise คืออะไร มีกี่สถานะ และ `.then()` คืออะไร | `Promise Basics` |
| อยากสร้าง Promise เองด้วย `new Promise()` และรู้ว่า `resolve` / `reject` คืออะไร | `Creating Promises` |
| อยากดัก error, recovery, และ cleanup ด้วย `.catch()` และ `.finally()` | `catch() & finally()` |
| อยากต่อหลายขั้นตอน ส่งค่าต่อใน chain และเข้าใจการลืม `return` | `Promise Chain` |
| อยากรอหลาย Promise พร้อมกันและทบทวนข้อผิดพลาดที่พบบ่อย | `Promise.all() & Common Mistakes` |