Async/Await ใน Array Loops Javascript

Watcharapong Tubjeen
DevNote
Published in
3 min readApr 27, 2019

--

ก่อนจะพูดถึง การ loop ในแบบ async /await ผมของพูดถึง loop synchronous ก่อนครับ อย่างที่รู้กันครับว่า loop synchronous ก็จะหน้าตาประมาณนี้

หรือแบบนี้

array.forEach((item) => {
// do something with item
});

หลายคนคงเคยใช้ รวมทั้งตัวผมเองด้วย ที่นี้ มาเข้าเรื่องของเรากันดีกว่า ต่อไปผมจะทำการ loop แบบ Asynchronous loops โดยผมจะทำแม่สูตรคูณขึ้นมา โดยผมจะทำการยกตัวอย่าง สองแบบครับ คือ ไม่รอผลลัพธ์ กับแบบ รอผลลัพธ์

ไม่รอผลลัพธ์

Output

Done 
2 * 1 : 2 ​​​​​
2 * 2 : 4 ​​​​​
2 * 3 : 6
2 * 4 : 8
2 * 5 : 10 ​​​​​
2 * 6 : 12
2 * 7 : 14 ​​​​​
2 * 8 : 16 ​​​​​
2 * 9 : 18
2 * 10 : 20
2 * 11 : 22
2 * 12 : 24

ซึ่งโดยรวมก็โอเคครับผลลัพธ์ถูกต้อง ซึ่งถ้าเราไม่ได้ต้องการเรื่องของการรอผลลัพธ์ที่ออกมา

ส่วนนี้คือตัวอย่างที่ใช้ในการ fetch API

Output

Finished!
Received Todo 2, Response: { ··· }
Received Todo 1, Response: { ··· }
Received Todo 3, Response: { ··· }

จะเห็นได้ว่า เรามีปัญหาเกิดขึ้นคือ ลำดับขั้นตอน ในทำงานของโปรแกรมไม่ถูกต้องกลายเป็นว่า มีการแสดง Finished ก่อน ถึงแม้ว่าเราจะมีการใช้ await ที่ foreach ก็ตาม แถมลำดับการ เรียก API ก็ยังไม่ถูกต้อง ตามที่เราต้องการอีก กลายเป็นว่า await fetch ที่เขียน ไม่มีการ รอผล response ของการ fetch ให้เสร็จก่อน มันกลับไป เรียกลำดับต่อไปในทันที

รอผลลัพธ์

ในขั้นตอนนี้ผมจะแสดงตัวอย่างการเขียน โดยรอผลลัพธ์ก่อน ซึ่งในครั่งนี้ผมจะทำการใช้ for… of ในการทำงาน เพื่อการ loop ที่ถูกต้องขึ้น แล้วทำไมถึงต้องใช้ for of เพราะว่า for… of นั้นใช้วนลูปรอบอ็อบเจ็กต์ประเภทที่เราเรียกว่า Iterable Objects หรือ object ที่จะเอามาใช้งานนั่นคือต้องทำตาม Iteration Protocol ซึ่ง array นั้นเป็น Iterable Objects อยู่แล้ว

Output

2 * 1 : 2 ​​​​​
2 * 2 : 4 ​​​​​
2 * 3 : 6
2 * 4 : 8
2 * 5 : 10 ​​​​​
2 * 6 : 12
2 * 7 : 14 ​​​​​
2 * 8 : 16 ​​​​​
2 * 9 : 18
2 * 10 : 20
2 * 11 : 22
2 * 12 : 24
Done

จะเห็นได้ว่า ผลลัพธ์ที่ออกมานั้นได้ทำตามลำดับขั้น โดนข้างในจะมีการรอผลลัพธ์ของ array ให้เสร็จก่อน แล้วถึงจะมาแสดง done

Promise.all fetch API

สำหรับการ fetch API หลายๆตัวพร้อมกันเราสามารถใช้ ได้ทั้ง for…of หรือ Promise.all ก็ตามแต่ชอบและความถนัด ในตัวอย่างต่อไปนี้ใช้ Promise.all

Output

Received Todo 1, Response: { ··· }
Received Todo 2, Response: { ··· }
Received Todo 3, Response: { ··· }
Finished!

ซึ่งจากการใช้ promise.all ได้แก้ไขปัญหาของการรอทุกคำขอให้เสร็จก่อนแล้วดำเนินการต่อไป

for…of VS Promise.all

ในการใช้งาน ระหว่าง for … of กับ Promise.all นั้น มีความแตกต่างกันอยู่ครับก็คือ for .. of จะเป็นการ ทำงานตามลำดับขั้นไปเรื่อยๆจนกว่าจะจบ loop ส่วน ของ Promise.all จะทำไปพร้อมๆกันแล้วปล่อยค่าออกมาครั่งเดียว ซึ่งผมจะยกตัวอย่าง ให้ดูถึงความแตกต่างครับ

ตัวอย่างนี้คือ for… of

Output

jon
JON
andrey
ANDREY
tania
TANIA
(3) [{…}, {…}, {…}]

ตัวอย่างนี้ Promise.all

Output

(3) [{…}, {…}, {…}]
jon
andrey
tania
JON
ANDREY
TANIA

👏 ก็จบแล้วน่ะครับสำหรับบทความนี้ ยังไงก็ ถ้าชอบก็ฝากแชร์กันด้วยน่ะครับ แล้วก็ถ้ามีอะไรผิด หรือ อธิบายไม่ถูกต้องก็ต้องขอโทษไว้น่ะที่นี้ด้วยน่ะครับ

--

--