เก็บ Global State ด้วย RxJS

ปัญหาหลัก ๆ ของการเขียน Web App คือ จะทำให้ยังไงให้ data ที่ควรจะเหมือนกัน ในแต่ละ Component เหมือนกัน ?

ยกตัวอย่างง่าย ๆ อย่างใน เว็บ Medium ถ้ามองไปด้านบนจะเห็น Navbar ที่มี User Photo อยู่มุมบนขวา ถ้าเข้าไปแก้รูปแล้ว Navbar จะรู้ได้ยังไงว่ารูปถูกเปลี่ยน ?

วิธีที่ง่าย ๆ ก็อาจจะ broadcast event ไปบอกทุก components ว่า User data เปลี่ยน ให้ไปดึง data มาใหม่ด้วย แล้วทุก Components ก็อาจจะส่ง http request ไปที่ server พร้อม ๆ กัน เพื่อไปเอา data ล่าสุด…

เพื่อให้ประหยัด request เราสามารถเก็บ data ไว้เป็น global state ได้ เมื่อ state เปลี่ยน, component ไหนที่ใช้ state อันนั้น ก็เอาค่าใหม่ไป update DOM

วิธีเก็บ data ใน global state มีหลายวิธี ในบทความนี้ผมจะขอพูดถึง การใช้ RxJS มาเก็บ Global state นะครับ


ทำความรู้จักกับ BehaviorSubject

ใน RxJS มี Subjects อยู่หลายประเภท เช่น AsyncSubject, PublishSubject, ReplySubject แต่ที่เหมาะที่สุดในการเอามาใช้เก็บ Global state ก็คือ BehaviorSubject

เมื่อเรา subscribe BehaviorSubject แล้ว เราจะได้ค่าล่าสุดทันที

const s = new BehaviorSubject(1)
s.next(2)
s.subscribe(console.log)
s.next(3)
// output
2
3

ต่างกับ PublishSubject (ใน RxJS PublishSubject คือ Subject) ที่จะได้ค่าหลังจากที่ subscribe ไปแล้ว

const s = new Subject()
s.next(2)
s.subscribe(console.log)
s.next(3)
// output
3

ดังนั้น เมื่อเรา subscribe BehaviorSubject เราจะได้ค่าของ State ปัจจุบัน และเมื่อ State ถูกเปลี่ยน เราก็จะได้ค่าของ State ใหม่ด้วย


ลองทำ Auth Service โดยใช้ RxJS กันบ้าง

เวลาใช้งานก็ง่าย ๆ เลย Component ไหนจะใช้ currentUser ก็ไป subscribe ที่ Auth.currentUser.subscribe(…) เมื่อ update user ก็ call Auth.fetchCurrentUser() ถ้าอยาก handle error ตอน call api ก็แค่ให้ fetchCurrentUser return Observable ออกมา


ปิดท้ายขายของ

ผมอาจจะได้มีโอกาสเปิด course เกี่ยวกับ RxJS + Firebase Realtime Database อีกไม่กี่เดือนข้างหน้านี้ ตอนนี้สามารถติดตาม course อื่น ๆ ได้ในเว็บ https://acourse.io ไปก่อนได้นะครับ xD

Like what you read? Give acoshift a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.