ในโลกของการพัฒนาซอฟต์แวร์ยุคใหม่ การที่โปรแกรมต้องมีการโต้ตอบกับระบบภายนอก ไม่ว่าจะเป็นการเรียก API จากเซิร์ฟเวอร์ หรือการอ่านข้อมูลจากฐานข้อมูล ย่อมเป็นสิ่งที่หลีกเลี่ยงไม่ได้ ปัญหาหลักที่นักพัฒนามักเผชิญคือ JavaScript เป็นภาษาแบบ Single-threaded ซึ่งหมายความว่าหากเราใช้โค้ดแบบเดิมๆ ในการรอคอย I/O (Input/Output) การทำงานทั้งหมดจะหยุดนิ่งหรือ “บล็อก” จนกว่าข้อมูลจะพร้อม ทำให้ประสบการณ์ผู้ใช้งานติดขัดและแอปพลิเคชันไม่มีประสิทธิภาพ
เจาะลึกรายละเอียดและประเด็นสำคัญ
การจัดการกับงานที่ต้องใช้เวลารอคอย (Asynchronous Operations) จึงเป็นหัวใจสำคัญของ JavaScript สมัยใหม่ เราได้ก้าวข้ามจาก Callback Hell ไปสู่โครงสร้างที่สะอาดและมีประสิทธิภาพกว่า นั่นคือ Promises และ async/await แนวคิดหลักคือการทำให้โค้ดที่ดูเหมือนว่ากำลังทำงานแบบ Synchronous แต่แท้จริงแล้วมันถูกจัดการอย่าง Non-blocking เพื่อให้เธรดหลักสามารถไปประมวลผลงานอื่น ๆ ต่อไปได้
Promises คือวัตถุที่ใช้แทนค่าในอนาคต (A placeholder for a value that will be available later) มันช่วยให้เราจัดการกับสถานะของ Asynchronous Operation ได้อย่างเป็นระเบียบ โดยมี 3 สถานะหลักคือ Pending, Fulfilled และ Rejected การใช้ `.then()` และ `.catch()` ทำให้การทำงานต่อเนื่องกันมีความชัดเจนและสามารถรวมศูนย์การจัดการข้อผิดพลาดได้ง่ายกว่า Callback แบบดั้งเดิม
JavaScript
async function fetchData(userId) {
try {
// จำลองการเรียก API ที่ใช้เวลา 1 วินาที
const response = await fetch(`https://api.example.com/users/${userId}`);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = await response.json();
return data; // ส่งค่าที่สำเร็จ (Fulfilled)
} catch (error) {
// การจัดการข้อผิดพลาดอย่างมืออาชีพด้วย try...catch
console.error("Failed to fetch user data:", error.message);
throw new Error("Could not retrieve data."); // โยนข้อผิดพลาดใหม่เพื่อให้ส่วนเรียกใช้ทราบ
}
}
// วิธีการใช้งาน: ต้อง await ภายใน async function เสมอ
async function main() {
try {
const userData = await fetchData(123);
console.log("User Data:", userData);
} catch (e) {
console.error("Operation failed at top level:", e.message);
}
}
main();