หัวข้อ 1: Callback, Promise และ async/await

คำจำกัดความ

Asynchronous Programming คือรูปแบบการเขียนโปรแกรมที่ไม่ต้องรอให้งานหนึ่งเสร็จก่อนเสมอ เช่น การอ่านไฟล์ เรียก API หรือรอ timer

%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#458588", "primaryTextColor": "#fbf1c7", "primaryBorderColor": "#fabd2f", "lineColor": "#a89984", "secondaryColor": "#b8bb26", "tertiaryColor": "#d3869b", "background": "#282828", "mainBkg": "#3c3836", "textColor": "#ebdbb2"}}}%%
flowchart TD
  A["Async Task
งานไม่ประสานเวลา"] --> B["Callback
ส่งฟังก์ชันไปเรียกกลับ"] A --> C["Promise
ตัวแทนผลลัพธ์อนาคต"] C --> D["Pending
รอดำเนินการ"] C --> E["Fulfilled
สำเร็จ"] C --> F["Rejected
ล้มเหลว"] C --> G["async/await
อ่านเหมือนโค้ดลำดับ"]

Callback และ Callback Hell

Callback คือฟังก์ชันที่ส่งเข้าไปเพื่อให้ถูกเรียกภายหลัง ปัญหาคือถ้าซ้อนหลายชั้นจะเกิด Callback Hell

function delay(ms, callback) {
  // รอเวลาตาม ms แล้วเรียก callback
  setTimeout(callback, ms);
}

delay(500, () => {
  console.log("โหลดผู้ใช้");
  delay(500, () => {
    console.log("โหลดรายวิชา");
    delay(500, () => {
      console.log("โหลดบทเรียน");
    });
  });
});

วิธีหลีกเลี่ยง:

Promise และ States

Promise คือตัวแทนผลลัพธ์ในอนาคต มีสถานะ Pending, Fulfilled, Rejected

function loadUser() {
  return new Promise((resolve, reject) => {
    const success = true;

    setTimeout(() => {
      if (success) {
        resolve({ id: 1, name: "Ana" });
      } else {
        reject(new Error("โหลดข้อมูลไม่สำเร็จ"));
      }
    }, 500);
  });
}

loadUser()
  .then(user => {
    // ทำงานเมื่อสำเร็จ
    console.log(user.name);
  })
  .catch(error => {
    // จัดการ error
    console.error(error.message);
  })
  .finally(() => {
    // ทำงานเสมอ
    console.log("จบการโหลด");
  });

Promise Helpers

Method พฤติกรรม เหมาะกับ
Promise.all() สำเร็จเมื่อทุกงานสำเร็จ ล้มทันทีเมื่อมีงานล้ม งานที่ต้องครบทุกผลลัพธ์
Promise.allSettled() รอทุกงาน ไม่ว่าสำเร็จหรือล้ม รายงานผลทุกงาน
Promise.race() คืนผลของงานที่จบก่อน timeout หรือแข่ง response
const a = Promise.resolve("A");
const b = Promise.resolve("B");

Promise.all([a, b]).then(results => {
  console.log(results); // ["A", "B"]
});

async/await และ try/catch

async function showUser() {
  try {
    // await ทำให้รอ Promise แบบอ่านง่าย
    const user = await loadUser();
    console.log(`ผู้ใช้: ${user.name}`);
  } catch (error) {
    console.error(`เกิดข้อผิดพลาด: ${error.message}`);
  } finally {
    console.log("ทำงานเสร็จ");
  }
}

// ตัวอย่างการใช้งาน
showUser();

สมการเวลา Sequential vs Parallel

Tparallel = max ( t1 , t2 , ... , tn )

โดยที่ Tparallel คือเวลารวมเมื่อทำงานพร้อมกัน, t₁...tₙ คือเวลาของแต่ละงาน, และ max คือเวลาของงานที่ช้าที่สุด

แบบทดสอบหลังเรียน

  1. Callback Hell คืออะไร
  2. Promise มีสถานะใดบ้าง
  3. .finally() ใช้ทำอะไร
  4. Promise.all() และ Promise.allSettled() ต่างกันอย่างไร
  5. try/catch กับ async/await ช่วยเรื่องใด

กลับสัปดาห์ที่ 6