ล้วงคอไปเตะตับ RxJS กับ Angular part 1
เพื่อนๆเคยเขียน Angular มาบ้างแล้ว เพื่อนๆรู้จัก Observable ไหม เพื่อนๆจัดการกับ data ที่ได้รับมาจาก APIs อย่างไร บทความนี้จะศึกษาและอธิบายสิ่งที่ RxJS ทำชนิดที่ว่าล้วงคอเพื่อไปดูตับ (ความคิด) RxJS ของ Angular กันครับ
รู้ว่าเขียน Angular เป็นอยู่แล้ว แต่ขอพื้นที่นี้ให้มือใหม่ได้ใช้ความคิดหน่อยเป็นไร
เพื่อนๆเคยได้ยินคำว่า Reactive programming ไหมครับ มันว่าด้วย รูปแบบการเขียนโปรแกรมแบบ asynchronous ที่เกี่ยวข้องกับพฤติกรรมของ data 2 ประการ
- data streams
- propagation of change
asynchronous
คือ เวลา คือของที่ยังมาไม่ถึง คือต้องคอยโดยไม่ทราบว่าเมื่อไรแล้วเสร็จ คือไม่คอยคำสั่งแบบมีลำดับก่อนหลัง ตัวอย่างเช่น
แม้ค้าเปิดร้านขายก๋วยเตี๋ยว ลูกค้าสั่ง “เส้นเล็กหมูลูกชิ้น” รายการที่ 1 นางก็เริ่มทำ เพิ่งลวกเส้นก๋วยเตี๋ยวได้ไม่นานปรากฏว่ามีลูกค้าอีกคนเดินเข้ามาสั่ง “เส้นใหญ่พิเศษลูกชิ้น” เป็นรายการที่ 2 แม่ค้าจึงบอกคอยก่อน หาที่นั่งก่อน เดี๋ยวทำให้
ลักษณะอย่างนี้คือไม่เป็น asynchronous แม่ค้าทำตามลำดับรายการ มาก่อนหลังมีผล
อีกตัวอย่าง
นายดำดูดีเป็นพนักงานต้อนรับของโรงแรม ลูกค้าต่างพื้นที่ที่จะมาพักที่นี่จำต้องถามนายดำเกือบทุกคน อาทิว่าห้องน้ำอยู่ไหน แลกเงินที่ไหน กระเป๋าวางไว้ที่ใด ช่วยไปขยับรถให้หน่อย ซื้อข้าวให้ที สั่งอาหารได้ไหม จะคืนห้องติดต่อใคร น้ำรั่วทำไงและอีกหลากหลายคำถาม นายดำทำงานมานานรู้ว่าต้องเจอกับอะไรบ้าง ถ้าจะให้เขามารับใช้ทุกคนในเวลาพร้อมกันมันเป็นไปไม่ได้ นายดำจึงมีผู้ช่วยหรือพวกพนักงานลูกน้องจำนวนหนึ่งที่สามารถเรียกใช้ให้ช่วยได้ตลอดเวลา
“อะไรนะครับ อ่อ ไปชั้น 15 ครับ เดี๋ยวผมให้คนยกกระเป๋าไปให้” นายดำกล่าวกับลูกค้าที่เพิ่งมาถึงและขอให้ผู้ช่วยของเขายกกระเป๋าไปส่งลูกค้าในอีก 5 นาที ระหว่างนั้นตนก็ต้อนรับลูกค้าคนถัดไป
“ได้ครับ แลกเงิน 3 พันบาทให้เป็นแบงค์ร้อยทั้งหมดนะครับ สักครู่ครับ” นายดำหันไปตอบลูกค้าอีกคนที่มาขอความช่วยเหลือ เขาส่งแบงค์พัน 3 ใบแก่ผู้ช่วย ผู้ช่วยก็ไปแลกให้ตามที่นายดำสั่ง
“ติดต่อช่างเรื่องท่อน้ำนะครับ ได้ครับผมดูแลให้ครับ ห้องคุณแจง 14/9 บ่ายโมงครับผม” แล้วนายดำก็ยกหูโทรศัพท์จัดการเรื่องนี้ให้ตามที่รับปากลูกค้าไว้
เพื่อนๆจะเห็นว่านายดำดูดีสามารถปฏิบัติหลายงานตามสั่งลูกค้าได้ทั้งหมดแทบจะในเวลาเดียวกัน เขาไม่รอให้งานแรกเสร็จก่อนจึงจะทำงานที่สอง เขาทำงานถัดไปได้ทันทีโดยไม่ต้องคอยผลลัพธ์ของงานก่อนหน้า ลักษณะอย่างนี้จึงเป็น asynchronous
data streams
พูดว่า data ทยอยส่งมาอย่างต่อเนื่อง
propagation of change
พูดว่า เมื่อได้รับ data มาแล้วจะจัดการต่ออย่างไร เปลี่ยนรูปแบบเลยไหม หรือคอย data ชุดถัดไปก่อนแล้วจึงปู้ยี่ปู้ยํา
RxJS
ย่อมาจาก Reactive Extensions for JavaScript หัวใจคือวิธีการจัดการ data streams แบบ asynchronous โดยใช้สิ่งที่เรียกว่า Observable
Observable
คือชนิดข้อมูลรูปแบบหนึ่ง (data type) และ RxJS ใช้ประโยชน์จากมันทำสิ่งต่อไปนี้
- ทำโค้ดธรรมดาให้กลายเป็น observable
- loop ข้อมูลด้วยรูปแบบ stream
- เปลี่ยนชนิดข้อมูลด้วยการ mapping
- stream สามารถ filtering
- รอคอยเพื่อประกอบร่างข้อมูลได้มากกว่าหนึ่ง stream (composing multiple streams)
หลายสิ่งของ JavaScript เช่น events, times, promises และอื่นๆถูกสร้างเป็น observable ได้หมด
Create an observable from a promise
เราสามารถสร้าง observable ได้จากหนึ่ง promise ใดๆก็ได้ เมื่อ promise ก็คือคำมั่น (อะจริงดิ แปลแบบนี้เลยเหรอ) ง่ายๆว่าเป็น asynchronous รอคอย data ที่ต้องการกลับมาจาก endpoint มันให้ผลสองอย่าง
- สำเร็จ ได้ data หรือ resources ที่ต้องการนั้น
- ล้มเหลว ได้ error กลับมา
ตัวอย่างต่อไปนี้ ผมได้สร้างโปรเจกต์ชื่อ books และใช้ HttpClient (อยู่ใน HttpClientModule) เรียกไปยัง endpoint ด้วย API ว่า GET /books สิ่งที่คาดหวังคือ array ของ JSON ของรายการหนังสือทั้งหมด
จากตัวอย่าง promise ของ HttpClient มีบริการ
- then เป็นผลสำเร็จ
- catch ล้มเหลว
- finally ทำทุกครั้งไม่ว่าผลนั้นจะสำเร็จหรือล้มเหลว
คราวนี้มาดู promise ของ RxJS กันหน่อย สามารถสร้างเป็น observable ได้ดังนี้
โดยที่ออบเจ็กต์ observable นั้นประกอบด้วย
- next เป็นผลสำเร็จและอาจยังคงมี data หรือ resources ที่ต้องการทยอยมาส่ง
- error ล้มเหลว
- complete ไม่มี data หรือ resources ที่ต้องการถูกส่งมาให้อีกแล้ว หรือ observable ถูก unsubscribe
ก่อนจะจากหัวข้อนี้ไป ขอแถม observable โดย HttpClient ซึ่งเขียนได้ง่ายมาก
Create an observable from a counter
เมธอด interval ของ RxJS เมื่อ subscribe จะให้ผลเป็น observable แบบ counter เพิ่มค่าทีละหนึ่งโดยอัตโนมัติ
Create an observable that creates an AJAX request
RxJS มีเมธอด ajax ให้ผลเป็น observable ได้
Create an observable from an event
ตัวอย่างต่อไปนี้คือการจับ mousemove event แล้วพิมพ์ค่าของพิกัด x และ y ออกมา
part แรกนี้เราได้เห็นภาพรวมแล้วว่า RxJS เป็นส่วนหนึ่งของ Angular เพื่อจัดการกับ asynchronous data streams ด้วย observable
ตัว observable คือออบเจ็กต์ JavaScript ที่ประกอบด้วย next, error และ complete
ค่อยเป็นค่อยไป ต่อจากนี้ก็จะดูเรื่อง common operators ครับ