วันนี้ได้ใช้ Promise.all คือ ถ้าหากเรามีหลาย async call แล้วอยากรอให้ทำงานเสร็จหมดก่อน จึงค่อยไปต่อ มี 2 ท่า คือ ใช้ Promise.all และ for แล้ว await ทีละอัน ซึ่งมันจะมีพฤติกรรมต่างกันอยู่ เลยอยากเขียนโน๊ตความแตกต่างไว้สักหน่อย


1. ใช้ Promise.all เรียกแบบ async ทั้งหมดก่อนแล้วค่อยรอ

ถ้าเราใช้ await Promise.all มันจะทำให้การทำงานแบบ async เกิดขึ้นเลยแล้วก็ค่อยรอให้ทุกๆอันเสร็จ

ตัวอย่าง เช่น

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then((values) => {
  console.log(values);
});

// หรือ

try {
  const [p1, p2, p3] = Promise.all([promise1, promise2, promise3])
} catch (e) {
  console.log(e)
}

Demo: Promise.all()


2.ใช้ for แล้ว await จะรอเสร็จทีละ 1 แล้วค่อยเรียกแบบ async

อีกวิธีนึง คือ ถ้าเราไม่ได้ใช้ Promise.all แล้วใช้วิธีการ loop ด้วย for แล้วเรียก await queryData ทีละอัน

เราสามารถเขียน code ได้ดังนี้

const names = ["john", "jane", "joe"];
const results = [];

for (const name of names) {
  results.push(await queryData(name));
}

Demo: For loop await

ความต่าง

ถ้าดูดีๆ จะเห็นว่า ถ้าเราใช้ for แล้ว await ทีละอันนั้น หมายความว่า จะต้องรอ await ทีละอันเสร็จก่อน แล้วไปทำอันถัดไป

แต่ถ้าเราไม่จำเป็นต้องรอทีละอัน ให้ใช้ Promise.all ไปเลยดีกว่า

ทีนี้มีสถานการณ์ไหนต้องรอบ้าง มันก็พอมีอยู่แต่คงไม่เยอะ เช่น เราต้องการเอาผลลัพธ์จาก async function ก่อนหน้าไปเป็น input ให้กับ async function ถัดไป เช่น

const params = ["john", "jane", "joe"];
let result = "";

for (const p of params) {
  result = await query(result, p);
}

Example loop await

จะเห็นว่าต้องรอ result ก่อนหน้าเพื่อเป็น input ให้กับ query ถัดไป แบบนี้ก็จะใช้ Promise.all ไม่ได้แล้วต้องเลือกใช้ for แล้ว await ทีละอันแทน