Overview
หลังจากเข้าใจ async/await พื้นฐานแล้ว ในระบบจริงเราจะเจอโจทย์ที่ซับซ้อนกว่านั้น เช่น "ถ้า API ล่มจะลองใหม่กี่ครั้ง?" หรือ "จะยิง API 10 ตัวพร้อมกันยังไงไม่ให้ Server พัง?" บทความนี้จะพาไปดู Pattern เหล่านั้นในเวอร์ชัน TypeScript
1. Retry Logic (ลองใหม่เมื่อล้มเหลว)
เหมาะสำหรับ Network Request ที่อาจมีความไม่เสถียรชั่วคราว
async function fetchWithRetry<T>(
fn: () => Promise<T>,
retries: number = 3,
delay: number = 1000,
): Promise<T> {
try {
return await fn();
} catch (error) {
if (retries <= 0) throw error;
console.log(`Failed. Retrying in ${delay}ms... (${retries} left)`);
await new Promise((res) => setTimeout(res, delay));
return fetchWithRetry(fn, retries - 1, delay * 2); // Exponential Backoff
}
}
// การใช้งาน
const data = await fetchWithRetry(() => fetchApi("/users"), 3);
2. Parallel vs Sequential Execution
เลือกรูปแบบการรันให้ถูกงาน
- Sequential: ทำทีละอย่าง (ช้า แต่ปลอดภัยถ้าลำดับสำคัญ)
- Parallel: ทำพร้อมกัน (เร็ว แต่อาจกิน Resource เยอะ)
- Promise.allSettled: รอทุกอันเสร็จ ไม่ว่าจะ Success หรือ Fail (เหมาะกับงานที่ไม่เกี่ยวข้องกัน)
async function loadDashboard() {
// 🔥 Parallel: ยิงพร้อมกัน 3 request
const [user, stats, logs] = await Promise.all([
fetchUser(),
fetchStats(),
fetchLogs(),
]);
return { user, stats, logs };
}
async function safeLoad() {
// 🛡️ AllSettled: ถ้าตัวนึงพัง ตัวอื่นยังรอด
const results = await Promise.allSettled([fetchUser(), fetchStats()]);
// ต้องมาเช็ค status เอง
results.forEach((res) => {
if (res.status === "fulfilled") console.log(res.value);
else console.error(res.reason);
});
}
3. Timeout Wrapper
ป้องกัน Promise รอแบบไม่มีที่สิ้นสุด (Hanging)
function withTimeout<T>(promise: Promise<T>, timeoutMs: number): Promise<T> {
const timeout = new Promise<never>((_, reject) =>
setTimeout(() => reject(new Error("Timeout exceeded")), timeoutMs),
);
return Promise.race([promise, timeout]);
}
// การใช้งาน
try {
const data = await withTimeout(fetchApi("/heavy-task"), 5000); // รอได้มากสุด 5 วิ
} catch (e) {
console.log("นานเกินไป ยกเลิก!");
}
Pitfalls (สิ่งที่ควรระวัง)
❌ Promise.all Fast Fail
Promise.all จะ throw error ทันทีถ้า มีอันใดอันหนึ่งพัง ทำให้เราไม่ได้ผลลัพธ์ของตัวอื่นที่ทำสำเร็จ ถ้าต้องการผลลัพธ์ทุกตัวให้ใช้ Promise.allSettled แทน