Overview
JavaScript เป็นภาษา Single Thread (ทำงานทีละอย่าง) ถ้าเราสั่งให้มัน "รอ" โหลดไฟล์โดยไม่มีกลไก Async โปรแกรมจะค้างไปเลย (Non-blocking I/O) การเขียน Asynchronous จึงเป็นท่าบังคับ
Key Ideas
1. Evolution of Async
- Callback: ยุคแรก ส่งฟังก์ชันไปเรียกทีหลัง (เกิดปัญหา Callback Hell ซ้อนกันเป็นปีระมิด)
- Promise: วัตถุที่สัญญาว่าจะให้ผลลัพธ์ในอนาคต (Success/Fail) แก้ปัญหา Nesting ได้ดีขึ้น (
.then()) - Async/Await (ปัจจุบัน): Syntax sugar ที่ทำให้เขียนโค้ด Async หน้าตาเหมือน Sync (อ่านง่ายสุด)
2. Async/Await Rules
awaitใช้ได้เฉพาะในฟังก์ชันที่มีasyncนำหน้า- ต้องใช้
try-catchเสมอ เพื่อจัดการ Error (เพราะไม่มี.catch()ให้ต่อท้ายแบบ Promise)
Example
// จำลอง API
function fetchUser(id: number): Promise<string> {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (id > 0) resolve(`User ${id}`);
else reject(new Error("Invalid ID"));
}, 1000);
});
}
// ✅ การใช้ Async/Await ที่ถูกต้อง
async function loadData() {
try {
console.log("Loading...");
const user = await fetchUser(1); // รอจนเสร็จ
console.log("Found:", user);
const user2 = await fetchUser(2); // รอ user 1 เสร็จก่อนค่อยทำ
console.log("Found:", user2);
} catch (error) {
console.error("Failed:", error);
} finally {
console.log("Finished process");
}
}
Pitfalls (สิ่งที่ควรระวัง)
❌ 1. ลืม await
ถ้าลืม await โปรแกรมจะไม่รอ และข้ามไปทำบรรทัดต่อไปทันที (ได้ค่าเป็น Promise object แทนที่จะเป็น value)
const user = fetchUser(1); // ไม่รอ!
console.log(user); // Promise { <pending> }
❌ 2. ใช้ await ใน Loop ทีละตัว (Sequential) โดยไม่จำเป็น
ถ้ารอบลูปไม่ได้สัมพันธ์กัน การรอทีละรอบทำให้ช้า
// ❌ ช้า: รอทีละอัน
for (const id of ids) {
await fetchUser(id);
}
// ✅ เร็ว: ยิงพร้อมกัน (Parallel) แล้วรอทีเดียว
await Promise.all(ids.map((id) => fetchUser(id)));