Back to notes
mastery-frontend-typescript
Featured

Advanced Async Patterns: เทคนิคจัดการ Asynchronous ขั้นสูง

ยกระดับการเขียน Async ให้ Robust ด้วยเทคนิค Retry Logic, Parallel Execution และการจัดการ Timeout ที่ปลอดภัย Type-Safe

January 29, 20262 min read readNNexis by Seereen

Overview

หลังจากเข้าใจ async/await พื้นฐานแล้ว ในระบบจริงเราจะเจอโจทย์ที่ซับซ้อนกว่านั้น เช่น "ถ้า API ล่มจะลองใหม่กี่ครั้ง?" หรือ "จะยิง API 10 ตัวพร้อมกันยังไงไม่ให้ Server พัง?" บทความนี้จะพาไปดู Pattern เหล่านั้นในเวอร์ชัน TypeScript

1. Retry Logic (ลองใหม่เมื่อล้มเหลว)

เหมาะสำหรับ Network Request ที่อาจมีความไม่เสถียรชั่วคราว

HLJS TYPESCRIPT
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 (เหมาะกับงานที่ไม่เกี่ยวข้องกัน)
HLJS TYPESCRIPT
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)

HLJS TYPESCRIPT
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 แทน

References

Share this note

© 2026 My Notes by Seereen