async/await เรามารู้จัก syntax ที่จะมาเปลี่ยนโลกของ javascript กัน

Panjamapong Sermsawatsri
PanJ’s Blog
Published in
2 min readDec 24, 2016

--

ในบรรดา feature ต่างๆ ที่อยู่บนมาตรฐาน ES2017 นั้น async/await เป็น feature ใหม่ที่น่าจับตามองมากที่สุด โดยที่จากที่แต่เดิมการเขียน asynchronous action นั้นต้องเขียน callback เต็มไปหมด ด้วย syntax async/await นั้นจะทำให้เราเขียนเหมือนกับเขียน synchronous action ธรรมดาเลย

Asynchronous กับ Synchronous คืออะไร

คำสองคำนี้สำคัญอย่างมากในภาษา JavaScript เพราะว่าด้วยธรรมชาติของภาษา JavaScript นั้นจะไม่ยอมให้มีคำสั่งใด ๆ มาขวางการทำงานในบรรทัดถัด ๆ ไป ซึ่งการที่ทำคำสั่งบรรทัดถัดไปทันทีเลย จะเรียกว่า Asynchronous ในทางกลับกัน การที่คำสั่งใด ๆ ที่หยุดรอจนกว่าคำสั่งจะเสร็จสมบูรณ์ เราจะเรียกว่า Synchronous

ตัวอย่างคำสั่ง Asynchronous ใน JavaScript ได้แก่ setTimeout

ส่วนตัวอย่างคำสั่ง Synchronous ใน JavaScript ได้แก่ confirm

จะเห็นว่าคำสั่ง confirm นั้นจะหยุดรอ user ตอบตกลงก่อนที่จะไปยังบรรทัดถัดไป ซึ่งจริง ๆ แล้วเป็นคำสั่งที่ผิดธรรมชาติของ JavaScript อันเป็นผลมาจากมรดกจาก Browser ในยุคก่อน ๆ

สำหรับการเรียกคำสั่ง Asynchronous นั้นจะแบ่งได้เป็นแบบต่าง ๆ ตามยุคสมัย

ยุคมืด: Callback

การที่จะทำคำสั่ง Asynchronous ให้เสร็จก่อนแล้วค่อยทำคำสั่งถัดไป เราจะใช้ callback โดย callback จะถูกเรียกเมื่อคำสั่ง Asynchronous ทำงานเสร็จแล้ว โดยธรรมเนียมแล้วเราจะให้ตัวแปรแรกของ callback เป็น error object ถ้าเป็น null แปลว่าไม่มี error

ยุคกลาง: Promise

การใช้ Callback ก่อให้เกิดปัญหาที่เรียกว่า Callback hell คือ callback ซ้อน callback เต็มไปหมด เลยเกิดวิธีแก้ปัญหาโดยการใช้ Promise

ตัวแปร Promise เป็นเหมือนกับคำสัญญาว่าจะทำคำสั่งนี้ให้เรานะ โดยมันจะมีอยู่ 3 สถานะก็คือ pending, resolved, rejected เมื่อเริ่มต้นทำคำสั่ง promise จะมีสถานะเป็น pending ถ้าทำเสร็จแล้วจะมีสถานะเป็น resolved โดยจะทำคำสั่งถัดไปที่อยู่ใน .then() และถ้าทำคำสั่งไม่สำเร็จ จะมีสถานะเป็น rejected และจะไม่ทำคำสั่งถัดไป แต่จะทำคำสั่งที่อยู่ใน .catch() แทน

ข้อดีคือไม่มี callback hell แล้ว และเวลาเราจะ handle error เราก็ไม่ต้องทำที่ละจุดใน callback แล้ว

ยุคใหม่: async/await

แต่ Promise ก็ยังมีข้อเสียอยู่ตรงที่จะต้องเขียน .then() ทุกครั้งที่ต้องการทำคำสั่งถัดไป ดังนั้น async/await จึงเป็นภาคต่อของ Promise โดยการเขียน async ไว้หน้า function จะเป็นการระบุว่า function นั้นทำงานแบบ asynchronous ตัวอย่างเช่น

เราจะเห็นว่ามี syntax await เพิ่มมาด้วย โดยการเติม await เข้าไปข้างหน้าการเรียก function นั้นจะหมายถึงว่าให้รอจนกว่าคำสั่งนั้นจะทำงานเสร็จแล้วค่อยส่งค่าออกไป

โดยการเรียก await นั้นจะสามารถใช้กับ function ได้ 2 แบบก็คือ function ที่ return ค่า Promise object และอีกแบบหนึ่งคือ async function

การมี async/await นั้นทำให้ code javascript ของเราดูเป็นผู้เป็นคนขึ้นมาทันที ในขณะเดียวกันก็ยังคง concept ของ javascript ที่สามารถเรียกให้ 2 คำสั่งทำงานพร้อมกันได้อย่างง่ายดาย เช่นกรณีที่เราอยากให้ doB ทำงานพร้อมกับ doC นั้นเราก็สามารถใช้ Promise.all ได้

สำหรับใครที่จะใช้ async/await บน browser จะแนะนำให้ผ่านการ compile ด้วย babel ก่อน จะทำให้เราใช้ feature บน ES2016, ES2017 ได้ใน browser ทั่วไปที่ไม่รองรับ โดยในตอนนี้เราสามารถ async/await แบบ native ไม่ต้อง compile ได้ใน Chrome v55 ขึ้นไป และใน Node 7.x ก็มีแผนที่จะออก update เพื่อรองรับ async/await ในเร็ว ๆ นี้

Update: สรุปว่าเราจะใช้ async/await ได้ใน Node 8.0.0 ที่มีแผนจะออกในเดือนเมษา 2017 นี้นะครับ (อ้างอิง https://github.com/nodejs/node/pull/9618#issuecomment-273821922)

สุดท้ายนี้ขอปิดท้ายบทความด้วยข้อความของท่านศาสดา TJ ผู้อยู่สร้าง npm module ยอดฮิตอย่างเช่น Express, Koa, ejs ที่ได้เคยกล่าวกับผมทาง email หลังจากที่ผมบอก TJ ว่าเรารอคุณกลับมาเขียน JavaScript อยู่นะ และเค้าจึงได้พูดถึง async/await ไว้ ว่าจะเป็นสิ่งที่มาพลิกเกมเลยทีเดียว

--

--