Frontend Academy · บทเรียน

Promise: then, catch, finally และ Promise.all

สร้างและเชื่อมต่อ Promise จัดการข้อผิดพลาดในบล็อก catch ทำความสะอาดใน finally และทำให้ Promise หลายรายการทำงานแบบขนานด้วย Promise.all

บทเรียน 3 จาก 413 ขั้นตอน

Promise: then, catch, finally และ Promise.all เป็นบทเรียน Frontend Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Frontend Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Frontend Academy มีบทเรียนทั้งหมด 4 บทเรียน

พรอมิสคืออะไร

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

การสร้างพรอมิส

สร้างพรอมิสด้วยตัวสร้าง new Promise(executor) ฟังก์ชันตัวดำเนินการจะได้รับฟังก์ชันเรียกกลับ resolve และ reject ให้เรียก resolve พร้อมค่าที่แสดงถึงความสำเร็จ หรือเรียก reject พร้อมข้อผิดพลาด

const delay = (ms) => new Promise((resolve) => {
  setTimeout(resolve, ms);
});

const fetchData = (url) => new Promise((resolve, reject) => {
  fetch(url)
    .then(res => res.json())
    .then(resolve)
    .catch(reject);
});

การจัดการผลสำเร็จของพรอมิส

promise.then(onFulfilled) จะลงทะเบียนฟังก์ชันเรียกกลับให้ทำงานเมื่อพรอมิสสำเร็จ ฟังก์ชันเรียกกลับจะได้รับค่าที่แก้ไขแล้ว .then() จะคืนค่าพรอมิสใหม่ จึงสามารถเชื่อมต่อการทำงานเป็นลำดับได้

fetch('/api/users')
  .then(response => response.json())
  .then(users => {
    console.log('Users:', users);
    return users.length;
  })
  .then(count => console.log('Count:', count));

การจัดการข้อผิดพลาดของพรอมิส

promise.catch(onRejected) ใช้จัดการการปฏิเสธ หากวางไว้ท้ายลำดับการเชื่อมต่อ จะตรวจจับข้อผิดพลาดจากขั้นตอนใด ๆ ที่อยู่ก่อนหน้าได้

fetch('/api/data')
  .then(res => {
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    return res.json();
  })
  .then(data => processData(data))
  .catch(err => {
    console.error('Failed:', err.message);
    showErrorToUser();
  });

การทำงานสุดท้าย — ทำงานเสมอ

promise.finally(onFinally) จะทำงานไม่ว่าพรอมิสจะสำเร็จหรือถูกปฏิเสธ เหมาะอย่างยิ่งสำหรับการล้างทรัพยากร เช่น ซ่อนตัวแสดงการโหลด ปลดล็อก หรือบันทึกข้อมูลการใช้งาน

showSpinner();
fetch('/api/data')
  .then(res => res.json())
  .then(render)
  .catch(handleError)
  .finally(() => hideSpinner()); // always runs

การเชื่อมต่อพรอมิส — การคืนค่า

คืนค่าจาก .then() แล้วค่านั้นจะกลายเป็นค่าที่แก้ไขแล้วของ .then() ถัดไป หากคืนค่าพรอมิสใหม่ ก็จะสามารถเชื่อมต่อการดำเนินการแบบอะซิงก์ให้ทำงานตามลำดับได้

getUser(id)
  .then(user => getOrders(user.id))  // return Promise
  .then(orders => orders[0])          // return value
  .then(order => console.log(order)); // receive order

Promise.all() — ทำงานแบบขนาน

Promise.all([p1, p2, p3]) จะรอให้พรอมิสทั้งหมดสำเร็จ แล้วคืนค่าอาร์เรย์ของผลลัพธ์ตามลำดับเดิม หากพรอมิสใดพรอมิสหนึ่งถูกปฏิเสธ การดำเนินการทั้งหมดจะถูกปฏิเสธทันที

const [user, posts, comments] = await Promise.all([
  fetch('/api/user/1').then(r => r.json()),
  fetch('/api/posts').then(r => r.json()),
  fetch('/api/comments').then(r => r.json()),
]);
// All three run in parallel — much faster than sequential

Promise.allSettled() — ไม่ล้มเหลวทันที

Promise.allSettled() จะรอให้พรอมิสทั้งหมดเข้าสู่สถานะสิ้นสุด (สำเร็จหรือถูกปฏิเสธ) แล้วคืนค่าอาร์เรย์ของออบเจ็กต์ผลลัพธ์ที่มีสถานะกับค่า หรือสถานะกับเหตุผล เหมาะเมื่อไม่ต้องการให้ความล้มเหลวเพียงรายการเดียวทำให้ผลลัพธ์ทั้งหมดสูญเสียไป

const results = await Promise.allSettled([p1, p2, p3]);
results.forEach(result => {
  if (result.status === 'fulfilled') use(result.value);
  else logError(result.reason);
});

Promise.race() และ Promise.any()

Promise.race() จะให้ผลสำเร็จหรือถูกปฏิเสธตามพรอมิสแรกที่เข้าสู่สถานะสิ้นสุด ส่วน Promise.any() จะให้ผลสำเร็จตามพรอมิสแรกที่สำเร็จ โดยไม่สนใจการปฏิเสธ และจะถูกปฏิเสธก็ต่อเมื่อทุกพรอมิสถูกปฏิเสธ เหมาะสำหรับการจำกัดเวลาและการทำงานสำรอง

// Timeout pattern:
const withTimeout = (promise, ms) => Promise.race([
  promise,
  new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), ms))
]);

การสร้างพรอมิสที่อยู่ในสถานะสิ้นสุดแล้ว

Promise.resolve(value) สร้างพรอมิสที่สำเร็จแล้วพร้อมค่า value ส่วน Promise.reject(error) สร้างพรอมิสที่ถูกปฏิเสธแล้ว มีประโยชน์สำหรับการทดสอบและฟังก์ชันปรับให้เข้ากัน

const p = Promise.resolve(42);
p.then(v => console.log(v)); // 42

เหตุการณ์การปฏิเสธที่ไม่ได้จัดการ

หากพรอมิสถูกปฏิเสธโดยไม่มี .catch() จะกลายเป็นการปฏิเสธที่ไม่ได้จัดการ เบราว์เซอร์สมัยใหม่และ Node.js จะแสดงคำเตือน ควรผูกตัวจัดการการปฏิเสธไว้เสมอ หรือใช้ try/catch ร่วมกับการทำงานแบบอะซิงก์/รอผล

window.addEventListener('unhandledrejection', event => {
  console.error('Unhandled rejection:', event.reason);
  event.preventDefault();
});

ตรวจสอบความเข้าใจ

เมธอดแบบสแตติกใดทำให้พรอมิสหลายรายการทำงานแบบขนาน และให้ผลสำเร็จเป็นอาร์เรย์ที่มีผลลัพธ์ทั้งหมด

ทบทวน: พรอมิส

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

เริ่มต้นได้ฟรี

เรียนรู้ HTML ด้วย AI tutor — ฟรี

เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป

คอร์ส
41
บทเรียน
163

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

บทเรียน “Promise: then, catch, finally และ Promise.all” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “Promise: then, catch, finally และ Promise.all” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Frontend Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Frontend Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “Promise: then, catch, finally และ Promise.all”

สร้างและเชื่อมต่อ Promise จัดการข้อผิดพลาดในบล็อก catch ทำความสะอาดใน finally และทำให้ Promise หลายรายการทำงานแบบขนานด้วย Promise.all คุณปฏิบัติ Frontend Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Frontend Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Frontend Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “Promise: then, catch, finally และ Promise.all” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Frontend Academy นี้ได้ไหม

ได้ บทเรียน Frontend Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

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

  1. Event Loop: Call Stack, Queue และ Microtasks
  2. Callback และ Callback Hell
  3. Promise: then, catch, finally และ Promise.all
  4. async/await และการจัดการข้อผิดพลาด
← กลับไปที่ Frontend Academy