Promise คือ object แทนผลลัพธ์ในอนาคต
มี 3 สถานะ: pending → fulfilled (สำเร็จ) หรือ rejected (ล้มเหลว) — เปลี่ยนได้ครั้งเดียว ไม่ย้อนกลับ
Promises
เข้าใจ Promise ในฐานะ object ที่แทนผลลัพธ์ในอนาคต — 3 สถานะ, Promise.resolve(), .then(), และความต่างระหว่าง Promise object กับค่าข้างใน
ในบท Callback function พื้นฐาน (บทที่ 68.8) และบท Timer (setTimeout) คุณเรียนว่า callback คือ function ที่ส่งให้คนอื่นเรียกทีหลัง — เช่น `setTimeout(callback, 1000)` รอ 1 วินาทีแล้วค่อยเรียก callback **`Promise`** ต่อยอดแนวคิดนี้ โดยห่อผลลัพธ์ของงาน asynchronous ไว้ใน **object** หนึ่งตัว — ทำให้รู้ได้ว่างานนั้นกำลังทำอยู่ สำเร็จแล้ว หรือล้มเหลว คิดง่าย ๆ: **Promise คือกล่องที่บอกว่า "เดี๋ยวแจ้ง"** — ตอนนี้กล่องยังไม่มีของ แต่รับปากว่าจะใส่ของเข้ามาในอนาคต ไม่ว่าจะเป็นค่าที่ต้องการ (สำเร็จ) หรือ error (ล้มเหลว)
Promise ≠ ค่าข้างใน
Promise เป็นกล่อง — ไม่ใช่ของในกล่อง คุณไม่ได้ค่าจาก Promise ทันที ต้องใช้ .then() เพื่อบอกว่า "เมื่อกล่องมีของแล้ว ให้ทำอะไร"
console.log(promise) แสดงตัว Promise object — ไม่ใช่ค่าข้างในโดยตรง
// สร้าง Promise ที่มีค่า "สวัสดี" ข้างใน
var promise = Promise.resolve("สวัสดี");
// log ตัว Promise object — ไม่ใช่ string "สวัสดี"
console.log(promise);
// Promise { "สวัสดี" }
// log ค่าธรรมดาเปรียบเทียบ
var plain = "สวัสดี";
console.log(plain);
// สวัสดีสังเกตความต่าง: - `console.log(promise)` → แสดง `Promise { "สวัสดี" }` — เป็น **object** - `console.log(plain)` → แสดง `สวัสดี` — เป็น **ค่าธรรมดา** นี่คือใจความสำคัญ: **Promise กับค่าข้างในเป็นคนละสิ่งกัน**
**Promise มี 3 สถานะ**: - **`pending`** — กำลังรอผลลัพธ์ (ยังไม่สำเร็จและยังไม่ล้มเหลว) - **`fulfilled`** — สำเร็จแล้ว (ได้ค่าที่ต้องการ) - **`rejected`** — ล้มเหลว (มี error เกิดขึ้น) สถานะเปลี่ยนได้แค่ **ครั้งเดียว** — จาก `pending` ไป `fulfilled` **หรือ** `rejected` — เมื่อเปลี่ยนแล้วจะไม่กลับมา `pending` อีก ``` pending → fulfilled (สำเร็จ ได้ค่า) pending → rejected (ล้มเหลว ได้ error) ```
`Promise.resolve(value)` เป็นวิธีที่ง่ายที่สุดในการสร้าง Promise — มันสร้าง Promise ที่ **fulfilled ทันที** ด้วยค่า `value` ที่ส่งเข้าไป ในบทนี้เราจะใช้ `Promise.resolve()` เป็นหลัก เพื่อให้เห็นภาพ Promise ก่อน — ในหน้าถัดไปคุณจะได้เรียน `new Promise()` สำหรับสร้าง Promise จากงานที่ยังไม่รู้ผล
Promise.resolve() รับค่าได้ทุกประเภท — string, number, object, array
// Promise ที่ resolve string
var greeting = Promise.resolve("สวัสดี");
console.log(greeting);
// Promise { "สวัสดี" }
// Promise ที่ resolve number
var score = Promise.resolve(95);
console.log(score);
// Promise { 95 }
// Promise ที่ resolve object
var user = Promise.resolve({ name: "Mali", role: "member" });
console.log(user);
// Promise { { name: "Mali", role: "member" } }ทุกครั้งที่ `console.log(promise)` คุณเห็น `Promise { ... }` — นั่นคือตัว **object** ไม่ใช่ค่าข้างใน **ค่าข้างใน Promise ไม่ออกมาทันที** — ถ้าคุณอยากได้ค่าจาก Promise ต้องใช้ `.then()` ซึ่งเป็นวิธีเดียวที่ถูกต้องในการเข้าถึงค่าข้างใน Promise
แม้ Promise.resolve() ก็ส่งค่าแบบ async
แม้ Promise.resolve() จะสร้าง Promise ที่สำเร็จทันที แต่ callback ใน .then() ก็ยังถูกเรียกแบบ asynchronous — ไม่ใช่ synchronous หมายความว่า .then() callback จะทำงานทีหลังโค้ดที่อยู่ข้างล่างมันเสมอ
**`.then(callback)`** ใช้ลงทะเบียน callback ที่จะถูกเรียกเมื่อ Promise **fulfilled** — callback นี้จะได้รับค่าที่ resolve ส่งมาเป็น parameter ถ้าเทียบกับบท Callbacks: callback ที่ส่งให้ `setTimeout` จะถูกเรียกเมื่อเวลาหมด — callback ที่ส่งให้ `.then()` จะถูกเรียกเมื่อ Promise สำเร็จ
.then(function (value) { ... }) — callback ได้รับค่าที่ resolve ส่งมา
var greeting = Promise.resolve("สวัสดี");
// .then() รับ callback — callback ได้ค่า "สวัสดี" จาก Promise
greeting.then(function (value) {
console.log("ได้รับ:", value);
});
// output:
// ได้รับ: สวัสดีสังเกตลำดับการทำงาน: callback ใน `.then()` ทำงาน **แบบ asynchronous** — โค้ดที่อยู่ข้างล่าง `.then()` จะรันก่อนเสมอ:
console.log ข้างล่าง .then() รันก่อน callback ใน .then() — เพราะ .then() เป็น async
var promise = Promise.resolve("ข้อมูล");
promise.then(function (value) {
console.log("ข้อ 2:", value); // รันทีหลัง
});
console.log("ข้อ 1: โค้ดหลัง .then()"); // รันก่อน
// output:
// ข้อ 1: โค้ดหลัง .then()
// ข้อ 2: ข้อมูลลำดับ output คือ **ข้อ 1 ก่อน → ข้อ 2 ทีหลัง** — ถึงแม้ Promise จะ resolve ทันทีก็ตาม นี่เป็นเพราะ `.then()` ส่ง callback เข้า callback queue แล้วรอ event loop เรียกในรอบถัดไป — เหมือนกับที่คุณเรียนในบท Event Loop **`.then()` คืนค่า Promise ตัวใหม่ทุกครั้ง** — ไม่ได้เปลี่ยน Promise ตัวเดิม แต่สร้างตัวใหม่ออกมา:
สังเกตว่า .then() ไม่ได้เปลี่ยน Promise ตัวเดิม แต่สร้าง Promise ตัวใหม่ออกมา
var first = Promise.resolve(1);
var second = first.then(function (n) {
return n + 2;
});
// ตัวเดิมไม่เปลี่ยน — ยังเป็น Promise { 1 }
console.log(first);
// Promise { 1 }
// ตัวใหม่ — เป็น Promise คนละตัวกับ first
console.log(second);
// Promise { 3 }
// รับค่าจาก second
second.then(function (result) {
console.log("second ได้ค่า:", result);
});
// output:
// Promise { 1 }
// Promise { 3 }
// second ได้ค่า: 3สังเกต: - `first` เป็น `Promise { 1 }` — ตัวเดิมไม่เปลี่ยน - `second` เป็น `Promise { 3 }` — ตัวใหม่ที่ `.then()` สร้างขึ้น - ทั้งสองเป็น **Promise คนละตัวกัน** คุณสมบัตินี้ (`.then()` คืน Promise ใหม่) คือรากฐานของ **Promise chain** — ที่คุณจะได้เรียนในหน้าถัดไป
นี่คือ mental model สำคัญที่สุดของบทนี้: **Promise เป็นกล่อง — ค่าข้างในเป็นของในกล่อง** คุณไม่สามารถ "เปิดกล่อง" ด้วยการ assign ค่าออกมาเหมือนตัวแปรธรรมดา — ต้องใช้ `.then()` เพื่อบอกว่า "เมื่อกล่องมีของแล้ว ให้ทำอะไร" ข้อผิดพลาดที่พบบ่อยที่สุดคือพยายามดึงค่าจาก Promise มาใช้นอก `.then()`:
result ยังเป็น undefined เพราะ .then() callback ยังไม่ทำงานตอน console.log ข้างนอกรัน
// ❌ ผิด: คิดว่า result จะมีค่าทันที
var result;
Promise.resolve("ข้อมูล").then(function (value) {
result = value; // กำหนดค่าใน .then()
});
console.log(result); // undefined — .then() ยังไม่ทำงาน!`result` เป็น `undefined` เพราะ `.then()` callback ทำงานแบบ **asynchronous** — ตอนที่ `console.log(result)` รัน callback ใน `.then()` ยังไม่ได้ทำงาน **วิธีที่ถูก**: ใช้ค่าจาก Promise **ภายใน `.then()` หรือต่อ chain**:
ทำงานกับค่าจาก Promise ภายใน .then() callback เท่านั้น
// ✅ ถูก: ใช้ค่าใน .then()
Promise.resolve("ข้อมูล").then(function (value) {
console.log("ได้ค่า:", value); // ได้ค่า: ข้อมูล
});
// ✅ ถูก: ต่อ chain — .then() ถัดไปได้ค่าจาก return
Promise.resolve(100)
.then(function (price) {
return price * 2; // ส่งค่าต่อให้ .then() ถัดไป
})
.then(function (doubled) {
console.log("สองเท่า:", doubled); // สองเท่า: 200
});ค่าจาก Promise ไม่ออกมาทันที — เสมอ
แม้จะใช้ Promise.resolve() ที่สำเร็จทันที ค่าก็ยังส่งแบบ async — นี่ไม่ใช่ bug แต่เป็นการออกแบบ: Promise รับมือกับงาน async ได้สม่ำเสมอเพราะมันไม่เคยคืนค่า sync ไม่ว่าจะยากหรือง่ายก็ตาม
มี 3 สถานะ: pending → fulfilled (สำเร็จ) หรือ rejected (ล้มเหลว) — เปลี่ยนได้ครั้งเดียว ไม่ย้อนกลับ
ค่า value ถูกห่ออยู่ใน Promise — ไม่ออกมาเป็นค่าธรรมดา
callback ได้รับค่าที่ resolve ส่งมา — ทำงานแบบ asynchronous เสมอ
ไม่ได้เปลี่ยน Promise ตัวเดิม — นี่คือรากฐานของ Promise chain
ใช้ .then() เพื่อเข้าถึงค่า — ห้ามพยายามเอาค่าออกมาใช้นอก .then()
แม้ Promise.resolve() ก็ตาม — .then() callback ทำงานทีหลังโค้ดที่อยู่ข้างล่างเสมอ