Skip to content

การจัดการ Control flow สำหรับ Node.js

ปัญหาอย่างหนึ่งของ Node.js (และ JavaScript) ซึ่งใช้ ES5 ที่มักจะถูกโจมตีจากสาวกภาษาอื่นเสมอมา (หรือแม้แต่คนเขียน Node.js อยู่แล้วก็เถอะ) คือเรื่อง callback hell ซึ่งจริงๆ มันก็ทำงานได้แหละครับแต่หน้าตาโปรแกรมจะแย่มากๆ แบบนี้

ถึงแม้ว่า Node.js เวอร์ชันล่าสุด (Version 4) หรือ io.js จะรองรับ syntax ใหม่ๆ ตามมาตรฐาน ES6 ซึ่งทำให้โค้ดสวยขึ้น แต่โค้ดส่วนมากก็ยังเขียนด้วย Es5 อยู่และธรรมชาติของ JavaScript เองที่จัดการการทำงาน Asynchronous ด้วย callback ดังนั้นเราหนีไม่พ้นหรอกครับ ที่ทำได้คือลด callback ซ้อน callback ให้มากที่สุดจนดูไม่เละเทะจนเกินไปกันดีกว่า ที่ผมแนะนำในโพสต์นี้คือ lib 2 ตัว Async และ Bluebird ครับ

Async

เป็น lib จัดการ control flow สไตล์ callback มี function สำหรับการทำงานหลายแบบทั้ง waterfall(), series(), parallel(), map(), mapSeries(), times() etc.

ยกตัวอย่างการใช้งาน async สักหน่อยแล้วกัน สมมุติว่าผมมีงานที่ต้องทำตาม step 1 2 3 แต่ละ step ได้ผลลัพธ์ออกมา โดยผลนั้นต้องถูกส่งต่อกันเรื่อยๆ ถ้าการทำงานเป็นแบบนี้ function ที่ผมต้องใช้คื อ waterfall() หรือการทำงานแบบขั้นน้ำตกนั่นเอง เขียนโค้ดจะได้แบบนี้ครับ

หรือถ้าต้องการทำหลาย function แบบ parallel ก็ทำแบบนี้ครับ

ถ้าอยากทำเป็น step เรียงกันแบบไม่มีการส่งต่อผลลัพธ์ก็ใช้ series() รูปแบบการใช้งานเหมือน parallel() แต่จะทำงานเรียงกันแทน ผลลัพธ์ของ callback สุดท้ายคือ error และ array ผลลัพธ์ของ function ที่เราส่งเข้าไปประมวลผล

รูปแบบการใช้งานอื่นๆ สามารถดูได้จาก document เลย Async มี document ค่อนข้างดี มีตัวอย่างให้ดูเยอะ

Ref: https://github.com/caolan/async

Bluebird

สำหรับมือใหม่อาจจะแปลกๆ นิดนึงกับการใช้งาน lib นี้เพราะใช้ Promise pattern ในการจัดการ control flow แนวคิดการทำงานของ promise ทำงานต่อกันในลักษณะ chain เช่น ทำ A แล้ว B เสร็จแล้วทำอะไรต่อ ผลลัพธ์จาก A -> B -> C ก็จะส่งต่อกันไปเรื่อยๆ (when … then …)

Promise เป็น  object ที่เก็บสถานะการทำงานของ function ไว้ Promise object มีได้หลายสถานะได้แก่

  • Fulfilled ทำงานสำเร็จ
  • Rejected ทำงานไม่สำเร็จ
  • Pending รอการประมวลผล
  • Settled ทำงานเสร็จแล้วแต่อาจจะ reject หรือ fulfilled ก็ได้

ล่าสุด Promise ถูกรวมเข้ามาใน ES6 แล้วสามารถใช้งานได้เลย แต่เพื่อความสะดวกแนะนำว่าใช้ Bluebird ดีกว่าครับเพราะมี function ช่วยทำงานหลากหลายกว่า สะดวกกว่าด้วย

โค้ดที่เขียนด้วย Promise pattern โดยใช้ bluebird หน้าตาจะเป็นแบบนี้ครับ

 

จะเห็นว่าโค้ดสวยงามขึ้นเหมือนเพราะ callback ซ้อน callback ลดลง ถ้าเป็นภาษาโปรแกรมทั่วไปก็คล้าย try … catch มากเลยครับ (แต่ไม่เหมือนกันนะ) การใช้งานแบบอื่นๆ ขอเอาไปเขียนโพสต์หน้าแล้วกันครับเพราะฟีเจอร์เยอะมาก

Ref: https://github.com/petkaantonov/bluebird

เลือกใช้กันตามสะดวกครับ

Be First to Comment

Leave a Reply

Your email address will not be published.