ปัญหาการใช้งาน async, await ใน Loop ของ Javascript

24 May 2022,
Share: 
Cover image

สวัสดีครับ ในบทความนี้เราจะมาเรียนรู้ปัญหาการใช้งาน Async, Await กับ Loop ชนิดต่างๆใน Javascript เมื่อเราใช้ Async, Await ใน Loop แต่ละชนิดจะให้ผลออกมาไม่เหมือนกัน Loop บางชนิดจะ Await รอในแต่ละครั้งของการวน Loop แต่สําหรับ Loop บางชนิดจะไม่รอ ดังนั้นมาดูกันครับว่า Loop แต่ละชนิดมีการทํางานกับ Async, Await อย่างไรบ้าง ดังนี้ครับ

For loop แบบธรรมดาทั่วไป

สําหรับ For loop แบบธรรมดาทั่วไป ทุกๆครั้งของการวน Loop จะ Await รอครับ มาดูตัวอย่างกัน

(async () => {
  const myProcess = [
    () => new Promise((resolve) => setTimeout(() => resolve('Task1 done.'), 5000)),
    () => new Promise((resolve) => setTimeout(() => resolve('Task2 done.'), 3000)),
    () => new Promise((resolve) => setTimeout(() => resolve('Task3 done.'), 1000)),
  ];

  for (let i = 0; i < myProcess.length; i++) {
    const res = await myProcess[i]();
    console.log(res);
  }

  console.log('Complete');
})();

จะได้ผลดังนี้

async-await-loop1

จากด้านบนผลลัพธ์แสดงผลออกมาตามลําดับคือ Task1, Task2, Task3, Complete หมายความว่า For loop รูปแบบนี้ จะ Await รอทุกครั้งที่วน Loop ครับ

for…in และ for…of

สําหรับ for…in และ for…of ทั้งสองแบบนี้จะ Await รอ และทํางานไปตามลําดับครับ มาดูตัวอย่างกันครับ

(async () => {
  const myProcess = [
    () => new Promise((resolve) => setTimeout(() => resolve('Task1_ done.'), 5000)),
    () => new Promise((resolve) => setTimeout(() => resolve('Task2 done.'), 3000)),
    () => new Promise((resolve) => setTimeout(() => resolve('Task3 done.'), 1000)),
  ];

  // for...in
  for (const item in myProcess) {
    const res = await myProcess[item]();
    console.log(res);
  }

  console.log('---------------');

  // for...of
  for (const item of myProcess) {
    const res = await item();
    console.log(res);
  }

  console.log('Complete');
})();

จะได้ผลดังนี้

async-await-loop3

Array forEach() and map()

สําหรับ forEach() และ map() จะมีการทํางานเหมือนกันคือ ทุกๆครั้งที่วน Loop จะไม่ Await รอครับ มาลองดูตัวอย่างของ forEach() กันก่อนครับ

(async () => {
  const myProcess = [
    () => new Promise((resolve) => setTimeout(() => resolve('Task1 done.'), 5000)),
    () => new Promise((resolve) => setTimeout(() => resolve('Task2 done.'), 3000)),
    () => new Promise((resolve) => setTimeout(() => resolve('Task3 done.'), 1000)),
  ];

  await myProcess.forEach(async (task) => {
    const res = await task();
    console.log(res);
  });

  console.log('Complete');
})();

จะได้ผลดังนี้

async-await-loop2

จากผลลัพธ์ด้านบน จะเห็นว่า Task ต่างๆ ไม่ทํางานไปตามลําดับ หมายความว่าใน Loop จะไม่รอให้ Task เสร็จก่อนแล้วจึงจะไปทํา Task ถัดไป คือจะวนทํารวดเดียวแล้วก็จบ Loop ไปเลย ถึงแม้ว่าเราจะใส่ await ไว้ข้างหน้า myProcess แล้วก็ตาม

มาดูตัวอย่างของ map() บ้างครับ

(async () => {
  const myProcess = [
    () => new Promise((resolve) => setTimeout(() => resolve('Task1 done.'), 5000)),
    () => new Promise((resolve) => setTimeout(() => resolve('Task2 done.'), 3000)),
    () => new Promise((resolve) => setTimeout(() => resolve('Task3 done.'), 1000)),
  ];

  const resultOfMap = await myProcess.map(async (it) => {
    const res = await it();
    console.log(res);
  });

  console.log('Result from map(): ', resultOfMap);
  console.log('Complete');
})();

จะได้ผลดังนี้

async-await-loop4

จะเห็นว่าทั้ง forEach() และ map() จะมีการทํางานไม่ต่างกัน แต่จะมีสิ่งที่ต่างกันคือ map() จะ return array ออกมาเท่านั้นเอง ซึ่งในตัวอย่างจะ return array ของ promise ออกมาเพราะว่า map() จะไม่ await รอครับ

สรุป

  • For loop แบบธรรมดาทั่วไป —> ✅ รอ
  • for…in และ for…of —> ✅ รอ
  • Array forEach() and map() —> ❌ ไม่รอ

มาถึงตรงนี้ทําให้เรารู้ว่าการใช้งาน Async, Await กับ Loop ชนิดต่างๆ ก็ได้ผลออกมาไม่เหมือนกัน ลองทําไปใช้งานกันดูนะครับ แล้วเจอกันใหม่บทความหน้านะครับ ขอบคุณครับ

Suggestion blogs

ESP8266 คืออะไร?

ESP8266 คืออะไร?ESP8266 คือ โมดูล wifi ภายในมีเฟิร์มแวร์ทํางานในลักษณะ Serial-to-WiFi ที่ช่วยให้อุปกรณ์อื่นๆ เช่น MCU สามารถต่อเข้ากับ internet ได้โดยใช้ port serial(ขา Tx, ขา Rx) และใช้คําสั่ง AT ในการควบคุมการทํางาน ต่อมาผู้พัฒนาได้พัฒนาเฟิร์มแวร์ NodeMcu ให้เป็น platform และใช้ภาษา LUA ในการเขียนโปรแกรม ด้วยความที่เป็น platform ที่สะดวกต่อการใช้งาน ทางผู้พัฒนาจึงจับ NodeMcu(ESP8266) ใส่เป็นบอร์ดหนึ่งใน Arduino IDE ด้วยซะเลย และได้พัฒนาให้สามารถเขียนโปรแกรมด้วยภาษา C/C++ สำหรับใครที่ใช้งาน Arduino อยู่แล้วสามารถใช้งานบน Arduino IDE ได้อย่างไม่อยากครับ

Configure the Linux Firewall for Docker Swarm on Ubuntu

บทความนี้จะเกี่ยวข้องกับการ Config Linux Firewall ให้สามารถใช้งาน Docker swarm ได้ ถ้าไม่ได้ Config เราจะเจอกับ Error นี้ "Timeout was reached before node was joined. The attempt to join the swarm will continue in the background. Use the "docker info" command to see the current swarm status of your node." ในขั้นตอนการ Join Swarm เพราะว่า Docker Swarm ใช้งาน port ดังต่อไปนี้

Docker Container

สําหรับบทความนี้จะมีเนื้อหาเกี่ยวกับ Docker Container นะครับ เราจะมาดู และทําความเข้าใจกันว่า Docker Container มันคืออะไร และเกี่ยวข้องกับ Docker Image อย่างไร


Copyright © 2019 - 2026 thiti.dev |  v1.60.0 |  Privacy policy | 

Build with ❤️ and Astro.

Github profile   Linkedin profile   Instagram   X profile   Nostr   Youtube channel   Telegram   Email contact   วงแหวนเว็บ