คลาส Promise ใน JavaScript

คลาส Promise ใน JavaScript

ในบทความนี้ เราจะอธิบายเกี่ยวกับคลาส Promise ใน JavaScript

YouTube Video

Promise

คลาส Promise เป็นคลาสสำหรับจัดการการทำงานแบบอะซิงโครนัส มันจัดการผลลัพธ์ในกรณีที่การทำงานสำเร็จ หรือจัดการข้อผิดพลาดในกรณีที่ล้มเหลว ในอดีต เราใช้งานฟังก์ชันคอลแบ็คเมื่อจำเป็นต้องรอการทำงานแบบอะซิงโครนัสให้เสร็จสิ้น แต่ Promise ทำให้สิ่งนี้ชัดเจนและทรงพลังยิ่งขึ้น

1const promise = new Promise((resolve, reject) => {
2    setTimeout(() => resolve("Done!"), 1000);
3});
4
5// Displays "Done!" after 1 second
6promise.then(result => console.log(result));
  • โค้ดนี้เป็นตัวอย่างของกระบวนการแบบอะซิงโครนัสที่แสดงข้อความ "เสร็จสิ้น!" หลังจากหนึ่งวินาที
    • ก่อนอื่นจะมีการสร้างอ็อบเจ็กต์ Promise ใหม่โดยใช้ new Promise อาร์กิวเมนต์เป็นฟังก์ชันที่รับ callback สองตัว: resolve สำหรับความสำเร็จและ reject สำหรับความล้มเหลว
    • setTimeout ถูกใช้เพื่อเรียก resolve() หลังจากหนึ่งวินาที
    • เมธอด then() ของอ็อบเจ็กต์ promise จะรอให้กระบวนการเสร็จสิ้นและแสดงผลลัพธ์

โครงสร้างพื้นฐาน

Promise คืออ็อบเจ็กต์ที่ท้ายที่สุดจะนำไปสู่สถานะ สำเร็จ หรือ ล้มเหลว

 1const promise = new Promise((resolve, reject) => {
 2    // Asynchronous operation
 3    // Flag indicating whether the operation was successful
 4    const success = true;
 5
 6    if (success) {
 7        resolve('Operation successful!');
 8    } else {
 9        reject('An error occurred');
10    }
11});
  • ในกรณี สำเร็จ จะมีการเรียกใช้ resolve()
  • ในกรณี ล้มเหลว จะมีการเรียกใช้ reject()

ออบเจกต์ Promise มีสามสถานะ

1promise
2    .then((result) => {
3        console.log(result);
4    })
5    .catch((error) => {
6        console.error(error);
7    })
  • รอดำเนินการ
    • กระบวนการอะซิงโครนัสยังไม่เสร็จสิ้น
  • สำเร็จ
    • กระบวนการอะซิงโครนัสสำเร็จ และผลลัพธ์ถูกส่งกลับโดย resolve() ผลลัพธ์จะได้รับโดยใช้เมธอด then()
  • ล้มเหลว
    • กระบวนการอะซิงโครนัสล้มเหลว และเกิดข้อผิดพลาดผ่าน reject() ข้อผิดพลาดจะได้รับโดยใช้เมธอด catch()

เมธอด then() และ catch()

เมื่อใช้ Promise คุณสามารถกำหนดว่าควรทำอะไรเมื่อการทำงานแบบอะซิงโครนัสเสร็จสมบูรณ์ คุณสามารถทำได้โดยใช้เมธอด then() และ catch()

then()

1const promise = new Promise((resolve, reject) => {
2    resolve('Operation successful!');
3});
4
5promise.then((result) => {
6    console.log(result);  // "Operation successful!"
7});
  • เมธอด then() ระบุฟังก์ชันที่จะถูกเรียกใช้งานเมื่อ Promise สำเร็จ

catch()

1const promise = new Promise((resolve, reject) => {
2    reject('An error occurred');
3});
4
5promise.catch((error) => {
6    console.error(error);  // "An error occurred"
7});
  • เมธอด catch() ระบุฟังก์ชันที่จะถูกเรียกใช้งานเมื่อ Promise ล้มเหลว

เมธอด finally()

 1const promise = new Promise((resolve, reject) => {
 2    resolve('Operation successful!');
 3});
 4
 5promise
 6    .then((result) => {
 7        console.log(result);
 8    })
 9    .catch((error) => {
10        console.error(error);
11    })
12    .finally(() => {
13        console.log('The operation has completed');
14    });
  • เมธอด finally() ระบุโค้ดที่จะถูกดำเนินการในขั้นตอนสุดท้าย ไม่ว่าจะ Promise สำเร็จหรือล้มเหลวก็ตาม

การเชื่อมต่อแบบ then()

then() ส่งกลับ Promise ใหม่ ดังนั้นคุณสามารถ เชื่อมต่อ then() ถัดไปได้

 1const promise = new Promise((resolve, reject) => {
 2    setTimeout(() => {
 3        resolve(1);
 4    }, 1000);
 5});
 6
 7promise
 8    .then(result => {
 9        console.log(result); // 1
10        return result + 1;
11    })
12    .then(result => {
13        console.log(result); // 2
14        return result + 1;
15    })
16    .then(result => {
17        console.log(result); // 3
18    })
19    .catch(error => {
20        console.error(error.message); // Something went wrong
21    });
  • ในโค้ดนี้ resolve() เริ่มต้นจะส่งผ่านค่า 1 และแต่ละค่าที่ถูกส่งกลับโดย then จะถูกส่งต่อไปยัง then ถัดไป
  • โดยการใช้ catch() คุณสามารถจัดการข้อผิดพลาดที่เกิดขึ้นในสายเชื่อมต่อทั้งหมดได้ในที่เดียว

ตัวอย่างเชิงปฏิบัติ

ตัวอย่างเช่น Promises มักใช้ในการดึงข้อมูลจากเซิร์ฟเวอร์ มาดูตัวอย่างที่ใช้ fetch() API กัน

 1fetch('https://codesparklab.com/json/example.json')
 2    .then(response => {
 3        if (!response.ok) {
 4            throw new Error('Network error');
 5        }
 6        return response.json();
 7    })
 8    .then(data => {
 9        console.log(data);
10    })
11    .catch(error => {
12        console.error('Error:', error);
13    });
  • ในโค้ดนี้, เนื่องจาก fetch() คืนค่าเป็น Promise, จึงใช้ then() ในการประมวลผลข้อมูลหลังจากได้รับการตอบกลับจากเซิร์ฟเวอร์ ข้อผิดพลาดจะถูกจัดการด้วย catch()

การจัดการ Promises หลายตัว

Promise.all()

หากต้องการดำเนินการ Promises หลายตัวพร้อมกันและดำเนินการต่อหากทุกตัวสำเร็จ, ให้ใช้ Promise.all()

 1const promise1 = Promise.resolve(1);
 2const promise2 = Promise.resolve(2);
 3const promise3 = Promise.resolve(3);
 4
 5Promise.all([promise1, promise2, promise3])
 6    .then((results) => {
 7        console.log(results);  // [1, 2, 3]
 8    })
 9    .catch((error) => {
10        console.error('Error :', error);
11    });
  • then() จะถูกเรียกใช้ก็ต่อเมื่อ Promises ทุกตัวสำเร็จ catch() จะถูกเรียกใช้หากแม้แต่ตัวเดียวล้มเหลว

Promise.allSettled()

หากคุณต้องการรัน Promise หลายรายการพร้อมกันและรับผลลัพธ์ทั้งหมดไม่ว่าจะสำเร็จหรือไม่ ให้ใช้ Promise.allSettled()

 1const promise1 = Promise.resolve(1);
 2const promise2 = Promise.reject("Failed");
 3const promise3 = Promise.resolve(3);
 4
 5Promise.allSettled([promise1, promise2, promise3])
 6    .then((results) => {
 7        results.forEach(result => console.log(result));
 8        // [
 9        //   { status: 'fulfilled', value: 1 },
10        //   { status: 'rejected', reason: 'Failed' },
11        //   { status: 'fulfilled', value: 3 }
12        // ]
13    });
  • then() จะถูกรันเมื่อ Promise ทั้งหมดสิ้นสุด (ไม่ว่าจะสำเร็จหรือล้มเหลว) แต่ละผลลัพธ์จะมีพร็อพเพอร์ตี้ status ('fulfilled' หรือ 'rejected') แม้ว่าบางอันจะล้มเหลว ก็จะไม่ส่งผลกระทบต่อการทำงานอื่น ๆ

Promise.race()

Promise.race() จะคืนค่าผลลัพธ์ของ Promise ที่เสร็จก่อน ไม่ว่าจะสำเร็จหรือไม่สำเร็จก็ตาม

1const promise1 = new Promise((resolve) => setTimeout(resolve, 100, 'First'));
2const promise2 = new Promise((resolve) => setTimeout(resolve, 500, 'Second'));
3
4Promise.race([promise1, promise2]).then((result) => {
5    console.log(result);  // "First"
6});
  • เช่นเดียวกับในตัวอย่างนี้ ผลลัพธ์ของ Promise ที่เสร็จสิ้นก่อนจะถูกรายงานกลับมา

ความสัมพันธ์กับ async/await

การใช้ไวยากรณ์ async/await ช่วยให้เขียน Promises ได้อย่างเข้าใจง่ายขึ้น ฟังก์ชัน async จะคืนค่าเป็น Promise เสมอ และ await จะรอให้ Promise ได้รับการแก้ไข

 1async function fetchData() {
 2    try {
 3        const response = await fetch('https://codesparklab.com/json/example.json');
 4        const data = await response.json();
 5        console.log(data);
 6    } catch (error) {
 7        console.error('Error :', error);
 8    }
 9}
10
11fetchData();

โดยการใช้ async/await แบบนี้, การดำเนินการแบบ asynchronous สามารถเขียนให้เหมือนโค้ดแบบ synchronous ทำให้อ่านง่ายขึ้น

สรุป

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

คุณสามารถติดตามบทความข้างต้นโดยใช้ Visual Studio Code บนช่อง YouTube ของเรา กรุณาตรวจสอบช่อง YouTube ด้วย

YouTube Video