เห็นเขาพูดว่า Asynchronous ใน Javascript ?
เห็นเขาพูดว่า Callback hell ?
เห็นเขาพูดว่า Promise ?
เห็นเขาพูดว่า Event loop ?

ไอ้เราก็ไม่ได้มีความรู้เรื่องต่างๆ เหล่านี้เลย
ดังนั้น มาลองศึกษาหาความรู้หน่อยสิว่า มันคืออะไร ?
เดี๋ยวจะคุยกับชาวบ้านเขาไม่รู้เรื่อง

เขาบอกว่าในปัจจุบันถ้าใครที่เขียน JavaScript หรือฝั่ง frontend
จำเป็นจะต้องเข้าใจกับคำว่า Asynchronous programming

แล้ว Asynchronous programming คืออะไร ?

เมื่อเราทำการเรียกใช้งาน function หนึ่งๆ แล้ว
function นั้นจะส่งผลการทำงานกลับมาให้ทันที
โดยไม่ต้องรอให้ function นั้น ทำงานจนเสร็จ

นั่นหมายความว่าคุณจะต้องส่งอะไรบางอย่างไปให้ function นี้
เพื่อสำหรับให้ส่งข้อมูลกลับมาภายหลังจากที่สำงานเสร็จ
ซึ่งจะเรียกว่าสิ่งนั้นว่า Callback function

โดยการทำงานแบบ Asynchronous นี้จะถูกใส่เข้าไปยัง browser ชนิดต่างๆ แล้วด้วย
และมันกลายเป็นประเด็นถกเถียงกันอย่างกว้างขวาง
ว่าแล้วควรจะใช้รูปแบบไหนดีล่ะ ?
เท่าที่ได้ยินมามีทั้ง Callback, Future, Promise, Functional Programming
ซึ่งมันเยอะมากๆ เลยนะ แต่ลองมาศึกษา Callback กับ Promise ก่อนดีกว่า
… ภาษาอะไรก็ไม่รู้ ท่าเยอะจริงๆ ….

ปัญหาอยู่ตรงไหนล่ะ ?

Screen Shot 2557-06-20 at 12.59.57 PM

มาถึงตรงนี้ผมไม่ต้องการถกเถียงอะไรมากนัก
แต่มาเริ่มดูที่ปัญหาดีกว่า ว่ามันมีอะไรกันบ้าง

เริ่มที่การเขียนโปรแกรมแบบ Aynchronous  กันก่อนดีกว่า

คำอธิบาย
เขียนด้วย Node.js ทำการอ่านไฟล์ mydata.json ขึ้นมา
ทำการเรียกใช้งาน function readFile() เพื่ออ่านข้อมูล
โดย function นี้จะมีการกำหนด callback function ขึ้นมา
ซึ่งเข้าทำงานเมื่อทำการอ่านข้อมูลจากไฟล์

ทำงานแบบ asynchronous เพราะว่า เมื่อเรียกใช้งาน function readFile()
และจะไม่ต้องรอให้ทำงานจบนั่นเอง
แต่จะทำการแจ้งกลับมาหลังจากที่ทำการอ่านข้อมูลจากไฟล์เสร็จสิ้น

ไม่เชื่อก็ลอง run โปรแกรมตัวอย่างดูหน่อยสิ
$node demo01.js

ได้ผลลัพธ์ดังนี้
After call read file
Got result

จากตัวอย่างแรกนี้ เป็นการใช้งาน callback ซึ่งใช้งานได้ดีนะ
อ่านง่าย เข้าใจง่าย และที่สำคัญทำงานได้ตามที่เราต้องการ

ต่อมาเราลองมาใช้งาน callback ได้ระบบที่ซับซ้อนขึ้นมาบ้าง
แล้วมาดูกันว่า callback ยังใช้งานได้ง่ายๆ และดีอยู่หรือไม่

ตัวอย่างการเรียก webservice 2 ตัวพร้อมกัน
โดยต้องแสดงผลลัพธ์หลังจากที่ดึงข้อมูลเสร็จจาก webservice ทั้งคู่
สามารถเขียนโปรแกรมได้ดังนี้

คำอธิบาย
จากตัวอย่างนั้นทำการประกาศตัวแปร response1 และ response2
เพื่อตรวจสอบสถานะการทำงานการดึงข้อมูลจาก webservice ทั้งสอง
โดยที่ callback ของการดึงข้อมูลจาก webservice
จะเรียกใช้งาน function next() ซึ่งทำการตรวจสอบสถานะการทำงาน
ของการดึงข้อมูลจาก webservice แล้วทำการเชื่อมต่อข้อมูล
และส่งผลลัพธ์กลับไปยังผู้เรียกใช้งาน
และถ้าการดึงข้อมูลจาก webservice ตัวใดเกิดผิดพลาด
จะส่ง error กลับไปแทน

เห็นไหมว่า callback นั้นทำให้เกิดปัญหาอื่นๆ ตามมา
เพื่อแก้ไขให้ระบบทำงานได้ ซึ่งทำให้เกิดความซับซ้อนขึ้นมาเรื่อยๆ
ลองจินตนาการดูว่า ถ้ามีการทำงานที่ซับซ้อนกว่านี้ จะจัดการอย่างไร ?

ดังนั้นจึงเป็นที่มาของ Callback hell
หรือบางสำนักจะเรียกว่า Pyramid of Doom

มักจะเกิดขึ้นเมื่อมีจำนวน action เยอะมากขึ้นในขั้นตอนการทำงาน
ทำให้มีการใช้งาน callback ซ้อนๆกันหลายชั้น ดังตัวอย่าง

โครงสร้างของ Callback เป็นดังรูป

callback-syndrome-cause

เลยมีแนวคิดอีกแบบในการจัดการเรียกว่า Promise

korean_pinky_promise_by_bcozy-d62mze7

เป็นอีกทางเลือกหนึ่งสำหรับการจัดการการทำงานแบบ asyncronous
โดยที่ Promise คือ object ที่ทำหน้าที่เก็บผลการทำงานของ asynchronous operation ต่างๆ
เก็บข้อมูลพวกสถานะการทำงาน และ จะทำการแจ้งให้ทราบ
เมื่อทำงานสำเร็จ หรือ ผิดพลาด

บางที่อาจจะบอกว่า
Promise มันคือ abstraction object/layer ของ Asynchronous programming
ซึ่งเป็น proxy object  เพื่อใช้สำหรับส่งค่าที่สำเร็จและผิดพลาด
กลับไปจาก function ที่ทำงานแบบ asynchronous

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

คำอธิบาย
ใน function asyncCall() นั้นไม่ต้องการ callback function แล้ว
และทำการส่ง Promise object กลับไป

โดย function then() จะถูกเรียกผ่าน Promise object
จะทำการส่ง Promise object กลับมาเช่นเดิม
และสามารถเรียก function then() ต่อกันสำหรับ Asynchronous operation อื่นๆ

ส่วน function fail() ถูกเรียกเมื่อมีความผิดพลาดเกิดขึ้น
เมื่อเกิดข้อผิดพลาดขึ้นมา จะทำการหยุดการทำงานของ operation อื่นๆ
ใน Promise object ให้อย่างอัตโนมัติ
ซึ่งเป็นจุดที่แตกต่างจาก Callback ที่ต้องตรวจสอบเอาเอง

และ Promise ทำให้เราสามารถอ่าน code ได้ง่ายขึ้นกว่าเดิมนะ
เนื่องจากไม่ต้องเขียนเป็นชั้นๆ แบบ callback

ภาพสรุปการทำงานของ Promise

Screen Shot 2557-06-21 at 10.22.56 AM

มาดูตัวอย่างของการใช้งาน Promise จริงๆ กันดีกว่า
โดยมี library ชื่อว่า Q ให้ใช้งาน ลองดูกัน

เริ่มต้นด้วยการอ่านไฟล์ เช่นเดิม

คำอธิบาย
funtion nfcall() ของ Q นั้นจะทำการแปลง function readFile() ของ file system
มาเป็น Promise object  ซึ่งทำให้สามารถใช้งาน Promise ได้
Q นั้นทำให้การเขียน Asynchronous programming นั้นง่ายขึ้น

ลงมาเขียนตัวอย่างเรียกใช้ webservice 2 ตัวกันดีกว่า
โดยทำการดึงข้อมูลผ่าน API ของ github ก็แล้วกัน
ตัวอย่าง code เป็นดังนี้

มาถึงตรงนี้ก็พอทำให้ผมเห็นว่าพื้นฐานของ Promise เป็นอย่างไร
รวมทั้งที่ไปที่มาของมันด้วย น่าจะทำให้ผมพอจะรู้เรื่องกับเขาขึ้นมาบ้างนิดหน่อย
เดี๋ยวออกไปฟังและเรียนรู้คนที่เขาทำกันจริงๆ ดีกว่า …