ดูแนวทางปฏิบัติแนะนำสำหรับการซิงค์สถานะแอปพลิเคชันระหว่าง IndexedDB กับไลบรารีการจัดการสถานะยอดนิยม
เมื่อผู้ใช้โหลดเว็บไซต์หรือแอปพลิเคชันเป็นครั้งแรก มักจะมีงานจำนวนมากที่เกี่ยวข้องกับการสร้างสถานะแอปพลิเคชันเริ่มต้นที่ใช้ในการแสดงผล UI ตัวอย่างเช่น บางครั้งแอปจำเป็นต้องตรวจสอบสิทธิ์ผู้ใช้ฝั่งไคลเอ็นต์ แล้วส่งคำขอ API หลายรายการก่อนที่จะมีข้อมูลทั้งหมดที่จำเป็นต้องแสดงในหน้าเว็บ
การจัดเก็บสถานะแอปพลิเคชันใน IndexedDB เป็นวิธีที่ยอดเยี่ยมในการเร่งเวลาในการโหลดสำหรับการเข้าชมซ้ำ จากนั้นแอปจะซิงค์กับบริการ API ในเบื้องหลังและอัปเดต UI ด้วยข้อมูลใหม่แบบ Lazy โดยใช้กลยุทธ์ stale-while-revalidate
อย่างไรก็ตาม เมื่อใช้ IndexedDB มีสิ่งสำคัญหลายอย่างที่ต้องพิจารณาซึ่งอาจไม่ชัดเจนในทันทีสำหรับนักพัฒนาซอฟต์แวร์ที่เพิ่งเริ่มใช้ API เอกสารนี้จะตอบคำถามที่พบบ่อยและพูดถึงสิ่งสำคัญที่สุดบางอย่างที่ควรคำนึงถึงเมื่อคงสถานะแอปพลิเคชันไว้ใน IndexedDB
ทำให้แอปคาดการณ์ได้
ความซับซ้อนมากมายเกี่ยวกับ IndexedDB เกิดจากความจริงที่ว่ามีปัจจัยหลายอย่างที่คุณ (นักพัฒนาซอฟต์แวร์) ควบคุมไม่ได้ ส่วนนี้จะอธิบายปัญหาหลายอย่างที่คุณต้องคำนึงถึงเมื่อทำงานกับ IndexedDB
การเขียนลงในพื้นที่เก็บข้อมูลอาจไม่สำเร็จ
ข้อผิดพลาดเมื่อเขียนไปยัง IndexedDB อาจเกิดขึ้นได้จากหลายสาเหตุ และในบางกรณี สาเหตุเหล่านี้อยู่นอกเหนือการควบคุมของคุณในฐานะนักพัฒนาซอฟต์แวร์ ตัวอย่างเช่น เบราว์เซอร์บางตัวไม่อนุญาตให้เขียนลงใน IndexedDB เมื่ออยู่ในโหมดการท่องเว็บแบบส่วนตัว นอกจากนี้ ยังมีความเป็นไปได้ที่ผู้ใช้อาจใช้อุปกรณ์ที่พื้นที่ในดิสก์ใกล้เต็ม และเบราว์เซอร์จะจำกัดไม่ให้คุณจัดเก็บข้อมูลใดๆ เลย
ด้วยเหตุนี้ คุณจึงต้องใช้การจัดการข้อผิดพลาดที่เหมาะสมในโค้ด IndexedDB เสมอ ซึ่งหมายความว่าโดยทั่วไปแล้ว คุณควรเก็บสถานะแอปพลิเคชันไว้ในหน่วยความจำ (นอกเหนือจากการจัดเก็บ) เพื่อไม่ให้ UI เสียหายเมื่อทำงานในโหมดการท่องเว็บแบบส่วนตัวหรือเมื่อไม่มีพื้นที่เก็บข้อมูล (แม้ว่าฟีเจอร์อื่นๆ ของแอปที่ต้องใช้พื้นที่เก็บข้อมูลจะไม่ทำงานก็ตาม)
ผู้ใช้อาจแก้ไขหรือลบข้อมูลที่จัดเก็บไว้
ฐานข้อมูลฝั่งไคลเอ็นต์ต่างจากฐานข้อมูลฝั่งเซิร์ฟเวอร์ที่คุณสามารถจำกัดการเข้าถึงที่ไม่ได้รับอนุญาต โดยส่วนขยายเบราว์เซอร์และเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์จะเข้าถึงฐานข้อมูลฝั่งไคลเอ็นต์ได้ และผู้ใช้สามารถล้างฐานข้อมูลดังกล่าวได้
แม้ว่าผู้ใช้จะไม่ค่อยแก้ไขข้อมูลที่จัดเก็บไว้ในเครื่อง แต่ก็มักจะล้างข้อมูลดังกล่าว แอปพลิเคชันของคุณต้องจัดการทั้ง 2 กรณีนี้ได้โดยไม่มีข้อผิดพลาด
ข้อมูลที่จัดเก็บไว้อาจไม่ใช่ข้อมูลล่าสุด
เช่นเดียวกับส่วนก่อนหน้า แม้ว่าผู้ใช้จะไม่ได้แก้ไขข้อมูลด้วยตนเอง แต่ก็เป็นไปได้ว่าข้อมูลที่ผู้ใช้มีในพื้นที่เก็บข้อมูลเขียนขึ้นโดยโค้ดเวอร์ชันก่อนหน้า ซึ่งอาจเป็นเวอร์ชันที่มีข้อบกพร่อง
IndexedDB มีการรองรับในตัวสำหรับเวอร์ชันสคีมาและการอัปเกรดโดยใช้เมธอด IDBOpenDBRequest.onupgradeneeded() แต่คุณยังคงต้องเขียนโค้ดอัปเกรดในลักษณะที่สามารถจัดการผู้ใช้ที่มาจากเวอร์ชันก่อนหน้า (รวมถึงเวอร์ชันที่มีข้อบกพร่อง)
การทำ Unit Test จะมีประโยชน์มากในกรณีนี้ เนื่องจากมักจะไม่สามารถทดสอบเส้นทางและกรณีการอัปเกรดที่เป็นไปได้ทั้งหมดด้วยตนเอง
ดูแลให้แอปมีประสิทธิภาพอยู่เสมอ
ฟีเจอร์หลักอย่างหนึ่งของ IndexedDB คือ API แบบอะซิงโครนัส แต่อย่าหลงคิดว่าคุณไม่ต้องกังวลเรื่องประสิทธิภาพเมื่อใช้งาน มีหลายกรณีที่การใช้งานที่ไม่เหมาะสมยังคงบล็อกเทรดหลักได้ ซึ่งอาจทำให้ไม่ตอบสนอง
ตามกฎทั่วไป การอ่านและเขียนไปยัง IndexedDB ไม่ควรมีขนาดใหญ่กว่าที่จำเป็นสำหรับข้อมูลที่เข้าถึง
แม้ว่า IndexedDB จะช่วยให้จัดเก็บออบเจ็กต์ที่ซ้อนกันขนาดใหญ่เป็นระเบียนเดียวได้ (และต้องยอมรับว่าการทำเช่นนี้ค่อนข้างสะดวกจากมุมมองของนักพัฒนาซอฟต์แวร์) แต่ก็ควรหลีกเลี่ยงแนวทางปฏิบัตินี้ เนื่องจากเมื่อ IndexedDB จัดเก็บออบเจ็กต์ ก่อนอื่นจะต้องสร้างโคลนที่มีโครงสร้างของออบเจ็กต์นั้น และกระบวนการโคลนที่มีโครงสร้างจะเกิดขึ้นในเทรดหลัก ยิ่งวัตถุมีขนาดใหญ่เท่าใด ระยะเวลาการบล็อกก็จะยิ่งนานขึ้นเท่านั้น
ซึ่งทำให้เกิดความท้าทายบางอย่างเมื่อวางแผนวิธีคงสถานะแอปพลิเคชันไว้ใน IndexedDB เนื่องจากไลบรารีการจัดการสถานะยอดนิยมส่วนใหญ่ (เช่น Redux) ทำงานโดยการจัดการโครงสร้างสถานะทั้งหมดเป็นออบเจ็กต์ JavaScript รายการเดียว
แม้ว่าการจัดการสถานะด้วยวิธีนี้จะมีประโยชน์มากมาย และการจัดเก็บแผนผังสถานะทั้งหมดเป็นระเบียนเดียวใน IndexedDB อาจดูน่าสนใจและสะดวก แต่การทำเช่นนี้หลังจากการเปลี่ยนแปลงทุกครั้ง (แม้ว่าจะมีการควบคุม/ลดจำนวนครั้ง) จะส่งผลให้เกิดการบล็อกเทรดหลักโดยไม่จำเป็น ซึ่งจะเพิ่มโอกาสที่จะเกิดข้อผิดพลาดในการเขียน และในบางกรณีอาจทำให้แท็บเบราว์เซอร์ขัดข้องหรือไม่ตอบสนอง
แทนที่จะจัดเก็บแผนผังสถานะทั้งหมดไว้ในระเบียนเดียว คุณควรแบ่งออกเป็นระเบียนย่อยๆ และอัปเดตเฉพาะระเบียนที่มีการเปลี่ยนแปลงจริงๆ
เช่นเดียวกับแนวทางปฏิบัติแนะนำส่วนใหญ่ แนวทางนี้ไม่ใช่กฎที่ต้องทำตามทั้งหมดหรือห้ามทำเลย ในกรณีที่ไม่สามารถแยกออบเจ็กต์สถานะและเขียนเฉพาะชุดการเปลี่ยนแปลงขั้นต่ำได้ การแยกข้อมูลออกเป็นแผนผังย่อยและเขียนเฉพาะแผนผังย่อยเหล่านั้นก็ยังคงดีกว่าการเขียนแผนผังสถานะทั้งหมดเสมอ การปรับปรุงเล็กๆ น้อยๆ ดีกว่าไม่มีการปรับปรุงเลย
สุดท้าย คุณควรวัดผลกระทบด้านประสิทธิภาพของโค้ดที่เขียนเสมอ แม้ว่าการเขียนข้อมูลขนาดเล็กไปยัง IndexedDB จะทำงานได้ดีกว่าการเขียนข้อมูลขนาดใหญ่ แต่สิ่งนี้จะสำคัญก็ต่อเมื่อการเขียนข้อมูลไปยัง IndexedDB ที่แอปพลิเคชันของคุณทำนั้นนำไปสู่งานที่ใช้เวลานานซึ่งบล็อกเทรดหลักและทำให้ประสบการณ์ของผู้ใช้แย่ลง การวัดผลเป็นสิ่งสำคัญเพื่อให้คุณเข้าใจว่ากำลังเพิ่มประสิทธิภาพเพื่ออะไร
บทสรุป
นักพัฒนาแอปสามารถใช้กลไกพื้นที่เก็บข้อมูลฝั่งไคลเอ็นต์ เช่น IndexedDB เพื่อปรับปรุงประสบการณ์ของผู้ใช้แอปพลิเคชัน ไม่เพียงแต่คงสถานะไว้ในเซสชันต่างๆ เท่านั้น แต่ยังลดเวลาที่ใช้ในการโหลดสถานะเริ่มต้นเมื่อเข้าชมซ้ำด้วย
แม้ว่าการใช้ IndexedDB อย่างเหมาะสมจะช่วยปรับปรุงประสบการณ์ของผู้ใช้ได้อย่างมาก แต่การใช้ IndexedDB อย่างไม่ถูกต้องหรือไม่สามารถจัดการกับกรณีข้อผิดพลาดอาจทำให้แอปเสียหายและผู้ใช้ไม่พอใจได้
เนื่องจากพื้นที่เก็บข้อมูลของไคลเอ็นต์เกี่ยวข้องกับปัจจัยหลายอย่างที่อยู่นอกเหนือการควบคุมของคุณ จึงเป็นสิ่งสำคัญที่โค้ดของคุณต้องได้รับการทดสอบอย่างดีและจัดการข้อผิดพลาดอย่างเหมาะสม แม้แต่ข้อผิดพลาดที่อาจดูเหมือนไม่น่าจะเกิดขึ้นในตอนแรก