ในโลกของการพัฒนาแอปพลิเคชันที่ใช้ฐานข้อมูล PostgreSQL การดำเนินการแบบไม่พร้อมกัน (Asynchronous Operations) เช่น การเรียกใช้ฟังก์ชันฐานข้อมูลที่ซับซ้อน หรือการเรียก API ข้ามเครือข่าย เป็นหัวใจสำคัญที่ทำให้ระบบมีประสิทธิภาพสูง ฟีเจอร์ async/await ใน TypeScript ช่วยให้เราสามารถจัดการโค้ดเหล่านี้ได้อย่างเป็นระเบียบคล้ายกับการเขียนเชิง Synchronous อย่างไรก็ตาม ความสะดวกสบายนี้ก็มาพร้อมกับความท้าทายในการจัดการข้อผิดพลาด (Error Handling) เมื่อการเชื่อมต่อล้มเหลว หรือคำสั่ง SQL มีปัญหา เราจำเป็นต้องเข้าใจกลไกการจับข้อผิดพลาดอย่างลึกซึ้ง เพื่อให้มั่นใจว่าแม้ส่วนหนึ่งของระบบจะล้มเหลว ระบบโดยรวมจะไม่หยุดชะงัก
หลักการจัดการข้อผิดพลาด Async/Await กับ PostgreSQL
เมื่อเราใช้ await โค้ดของเรากำลังรอผลลัพธ์จาก Promise ที่ส่งผลมาจากการเรียกใช้ฐานข้อมูล (เช่น การรันคำสั่ง await pool.query(...)) หากคำสั่ง SQL นั้นเกิดข้อผิดพลาด (เช่น Unique Constraint Violation หรือ Syntax Error) Promise นั้นจะถูก Reject ทันที การปฏิเสธ (Reject) นี้เองคือ Exception ที่เราต้องดักจับ
เราจึงต้องใช้บล็อกควบคุม try...catch เพื่อทำหน้าที่เป็นกลไกการตรวจจับข้อผิดพลาดหลัก โดยการวาง try...catch รอบคำสั่ง await ที่ติดต่อกับ PostgreSQL โดยตรง จะทำให้เราสามารถรับข้อผิดพลาดที่เกิดขึ้นในระดับฐานข้อมูลมาจัดการและตอบสนองได้อย่างเหมาะสม
ตัวอย่างการดักจับข้อผิดพลาด SQL ใน TypeScript
ตัวอย่างนี้จำลองการเรียกใช้ฟังก์ชันฐานข้อมูลที่อาจเกิดข้อผิดพลาด (เช่น การพยายามใส่ข้อมูลที่ซ้ำกัน) และแสดงวิธีการดักจับข้อผิดพลาดที่เกิดขึ้น:
TypeScript
// สมมติว่า 'dbClient' คือการเชื่อมต่อ PostgreSQL ที่มีการจัดการ Promise แล้ว
async function processUserData(data: string[]): Promise<void> {
try {
// 1. คำสั่งที่คาดหวังให้ทำงาน (Try Block)
// สมมติว่าฟังก์ชันนี้รันคำสั่ง INSERT ที่ PostgreSQL
await dbClient.query(
"INSERT INTO users (ids) VALUES ($1)",
[data.join(',')]
);
console.log("✅ ข้อมูลถูกบันทึกเรียบร้อยแล้ว.");
} catch (error) {
// 2. การดักจับข้อผิดพลาด (Catch Block)
// ในกรณีที่ PostgreSQL Reject (เช่น Unique Constraint Violation)
if (error instanceof Error) {
console.error("❌ เกิดข้อผิดพลาดในการประมวลผลข้อมูล:");
// ตรวจสอบรหัสข้อผิดพลาดเฉพาะของ PostgreSQL (เช่น 23505 สำหรับ Unique Violation)
if (error.code === '23505') {
console.error(" [DB Error]: ข้อมูลนี้มีอยู่แล้ว กรุณาลองใหม่ด้วยค่าอื่น.");
} else {
console.error(" [System Error]: ข้อผิดพลาดทั่วไป: ", error.message);
}
}
}
}
// การเรียกใช้งานฟังก์ชัน
// processUserData(['1,2,3']);
สรุปแนวปฏิบัติที่ดีที่สุด (Best Practices)
การใช้ try...catch กับ await ไม่เพียงแค่ช่วยป้องกันไม่ให้แอปพลิเคชันล่มเท่านั้น แต่ยังช่วยให้เราสามารถแยกแยะประเภทของข้อผิดพลาดได้อย่างแม่นยำ (เช่น แยกแยะระหว่างข้อผิดพลาดด้านเครือข่าย, ข้อผิดพลาดด้านไวยากรณ์ SQL, หรือข้อผิดพลาดด้าน Business Logic) การตรวจสอบรหัสข้อผิดพลาด (Error Code) ที่ส่งกลับมาจาก PostgreSQL โดยตรงจึงเป็นสิ่งสำคัญที่สุดสำหรับสถาปนิกระบบที่ต้องการสร้างระบบที่มีความทนทาน (Resilience) สูง