วัน: 12 พฤศจิกายน 2018

TypeScript: ใช้งาน Promise ที่ทำงานเสร็จเป็นลำดับแรกTypeScript: ใช้งาน Promise ที่ทำงานเสร็จเป็นลำดับแรก

ทำความเข้าใจการทำงานแบบอะซิงโครนัสด้วย Promises ใน TypeScript

ในโลกของการพัฒนาเว็บสมัยใหม่ การดำเนินการส่วนใหญ่มักไม่ใช่สิ่งที่เกิดขึ้นทันที แต่เป็นการเรียกใช้ API ข้อมูลภายนอก หรือการอ่านไฟล์ ซึ่งเป็นกระบวนการที่เรียกว่า ‘Asynchronous’ เพื่อให้แอปพลิเคชันไม่หยุดชะงักขณะรอผลลัพธ์ เราจึงต้องอาศัยกลไกอย่าง Promise เข้ามาช่วยในการจัดการสถานะของคำมั่นสัญญาเหล่านี้

อย่างไรก็ตาม ปัญหาสำคัญไม่ได้อยู่ที่เพียงแค่รับรู้ว่าข้อมูลจะพร้อมเมื่อใดเท่านั้น แต่อยู่ที่ลำดับขั้นตอน หากเรามีชุดงานหลายอย่างที่จำเป็นต้องเสร็จสิ้นตามคิว เช่น ต้องดึง User ID ก่อน แล้วค่อยนำ ID นั้นไปค้นหา Profile ต่อ นี่คือกรณีที่เราต้องการ ‘Promises ที่ทำงานเสร็จเป็นลำดับ’ อย่างเคร่งครัด ไม่สามารถข้ามหรือสลับกันได้


หลักการพื้นฐาน: ความแตกต่างระหว่าง Parallel และ Sequential Execution

Promise ถูกออกแบบมาเพื่อระบุค่าที่จะส่งคืนในอนาคต เมื่อพูดถึงการรันโค้ด ควรทำความเข้าใจก่อนว่าจะเกิดอะไรขึ้นหากเรารวม Promises หลายตัวเข้าด้วยกัน:

  • Parallel (คู่ขนาน): คือการเริ่มดำเนินการทั้งหมด ณ เวลาเดียวกัน โดยใช้ `Promise.all()` เหมาะสำหรับภาระหน้าที่ที่ไม่เกี่ยวข้องกันเลยและสามารถถูกประมวลผลแยกจากกัน
  • Sequential (เรียงลำดับ/ต่อเนื่อง): เป็นรูปแบบที่คุณจะต้องรอให้ Task A เสร็จสมบูรณ์จนได้รับผลลัพธ์แล้ว จึงจะเริ่มต้น Task B ด้วย Input จาก Task A ได้ การจัดการแบบนี้จึงมีความซับซ้อนกว่าแต่ก็แม่นยำในการจำลอง Workflow ทางธุรกิจจริง ๆ

กลไกสำคัญสำหรับการจัดลำดับขั้นงาน Promise Chaining & Async/Await

วิธีการมาตรฐานที่เคยใช้มาก่อนหน้านี้คือเทคนิค ‘Chaining’ ซึ่งอาศัยเมธอด `.then()` ต่อท้ายอย่างไม่สิ้นสุด ทำให้โครงสร้างของฟังก์ชันดูยาวเหยียด แต่เมื่อเวลาผ่านไป JavaScript Engine ก็ได้เปิดตัว Syntax ที่ทรงพลังยิ่งกว่า นั่นคือ async และ await

// ตัวอย่างโค้ดกับการรันตามลำดับขั้นตอนด้วย async/await
const fetchUserData = async (userId) => {
  try {
    console.log(