แนวทางปฏิบัติแนะนำในการเก็บสถานะแอปพลิเคชันถาวรด้วย IndexedDB

เรียนรู้แนวทางปฏิบัติแนะนำสำหรับการซิงค์สถานะแอปพลิเคชันระหว่าง IndexedDB และไลบรารีการจัดการสถานะยอดนิยม

เมื่อผู้ใช้โหลดเว็บไซต์หรือแอปพลิเคชันเป็นครั้งแรก มักจะมีงานจำนวนมากที่เกี่ยวข้องกับการสร้างสถานะแอปพลิเคชันเริ่มต้นที่ใช้เพื่อแสดงผล UI ตัวอย่างเช่น บางครั้งแอปต้องตรวจสอบสิทธิ์ฝั่งไคลเอ็นต์ของผู้ใช้ จากนั้นส่งคำขอ API หลายรายการก่อนที่แอปจะมีข้อมูลทั้งหมดที่จำเป็นต่อการแสดงในหน้าเว็บ

การจัดเก็บสถานะแอปพลิเคชันใน IndexedDB เป็นวิธีที่ยอดเยี่ยมในการเร่งเวลาในการโหลดสำหรับการเข้าชมซ้ำ จากนั้นแอปจะซิงค์กับบริการ API ใดก็ได้ในเบื้องหลัง และอัปเดต UI ด้วยข้อมูลใหม่แบบล่าช้าโดยใช้กลยุทธ์ตรวจสอบอีกครั้งเมื่อข้อมูลล้าสมัย

อย่างไรก็ตาม เมื่อใช้ IndexedDB มีข้อสําคัญหลายประการที่ควรพิจารณา ซึ่งนักพัฒนาซอฟต์แวร์มือใหม่อาจไม่เข้าใจในทันที เอกสารนี้จะตอบคําถามที่พบบ่อยและกล่าวถึงสิ่งสําคัญบางประการที่ควรคํานึงถึงเมื่อเก็บสถานะแอปพลิเคชันไว้ใน IndexedDB

ทำให้แอปคาดการณ์ได้อยู่เสมอ

ความซับซ้อนมากมายเกี่ยวกับ IndexedDB เกิดจากข้อเท็จจริงที่ว่า มีปัจจัยมากมายที่คุณ (นักพัฒนาซอฟต์แวร์) ไม่สามารถควบคุมได้ ส่วนนี้จะอธิบายปัญหามากมายที่คุณต้องคำนึงถึงเมื่อทำงานกับ IndexedDB

การเขียนไปยังพื้นที่เก็บข้อมูลอาจล้มเหลว

ข้อผิดพลาดในการเขียนลงใน IndexedDB อาจเกิดขึ้นได้จากหลายสาเหตุ และในบางกรณี สาเหตุเหล่านี้อยู่นอกเหนือการควบคุมของคุณในฐานะนักพัฒนาซอฟต์แวร์ ตัวอย่างเช่น บางเบราว์เซอร์ไม่อนุญาตให้เขียนไปยัง IndexedDB เมื่ออยู่ในโหมดการเรียกดูแบบส่วนตัว นอกจากนี้ ยังเป็นไปได้ว่าผู้ใช้กำลังใช้อุปกรณ์ที่เกือบมีพื้นที่ในดิสก์แล้ว และเบราว์เซอร์จะจำกัดไม่ให้คุณจัดเก็บสิ่งใดเลย

ด้วยเหตุนี้ คุณจึงควรใช้การจัดการข้อผิดพลาดที่เหมาะสมในโค้ด IndexedDB เสมอ ซึ่งหมายความว่าโดยทั่วไปแล้ว คุณควรเก็บสถานะแอปพลิเคชันในหน่วยความจำ (นอกเหนือจากการจัดเก็บ) เพื่อให้ UI ไม่ขัดข้องเมื่อทำงานในโหมดการท่องเว็บส่วนตัวหรือเมื่อพื้นที่เก็บข้อมูลไม่พร้อมใช้งาน (แม้ว่าฟีเจอร์อื่นๆ ของแอปที่ต้องใช้พื้นที่เก็บข้อมูลจะใช้งานไม่ได้ก็ตาม)

ผู้ใช้อาจแก้ไขหรือลบข้อมูลที่จัดเก็บไว้

ซึ่งต่างจากฐานข้อมูลฝั่งเซิร์ฟเวอร์ที่คุณจำกัดการเข้าถึงที่ไม่ได้รับอนุญาตได้ ส่วนขยายของเบราว์เซอร์และเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์จะเข้าถึงฐานข้อมูลของไคลเอ็นต์ได้ และผู้ใช้ล้างฐานข้อมูลดังกล่าวได้

แม้ว่าอาจไม่ใช่เรื่องแปลกที่ผู้ใช้จะแก้ไขข้อมูลที่เก็บไว้ในเครื่อง แต่การล้างข้อมูลนั้นก็เป็นเรื่องปกติ แอปพลิเคชันต้องจัดการทั้ง 2 กรณีนี้โดยไม่มีข้อผิดพลาด

ข้อมูลที่จัดเก็บไว้อาจล้าสมัย

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

IndexedDB มีการสนับสนุนในตัวสำหรับเวอร์ชันสคีมาและการอัปเกรดโดยใช้เมธอด IDBOpenDBRequest.onupgradeneeded() อย่างไรก็ตาม คุณยังคงต้องเขียนโค้ดการอัปเกรดให้สามารถจัดการผู้ใช้ที่มาจากเวอร์ชันก่อนหน้าได้ (รวมถึงเวอร์ชันที่มีข้อบกพร่อง)

การทดสอบ 1 หน่วยมีประโยชน์มากเนื่องจากมักจะเป็นไปไม่ได้ที่จะทดสอบเส้นทางการอัปเกรดและกรณีทั้งหมดด้วยตนเอง

รักษาประสิทธิภาพของแอป

หนึ่งในฟีเจอร์หลักของ IndexedDB คือ API แบบแอซิงโครนัส แต่อย่าคิดว่าคุณไม่ต้องกังวลเรื่องประสิทธิภาพเมื่อใช้ API นี้ มีหลายกรณีที่การใช้งานที่ไม่เหมาะสมยังคงบล็อกเทรดหลักได้ ซึ่งอาจทำให้เกิดการไม่ตอบสนองได้

โดยทั่วไปแล้ว การอ่านและเขียนลงใน IndexedDB ไม่ควรมีขนาดใหญ่เกินกว่าที่จําเป็นสําหรับข้อมูลที่เข้าถึง

แม้ว่า IndexedDB จะช่วยให้จัดเก็บออบเจ็กต์ขนาดใหญ่ที่ซ้อนอยู่เป็นระเบียนเดียวได้ (และการทำเช่นนี้ก็ค่อนข้างสะดวกในมุมมองของนักพัฒนาซอฟต์แวร์) คุณควรหลีกเลี่ยงแนวทางปฏิบัตินี้ สาเหตุก็เพราะเมื่อ IndexedDB จัดเก็บออบเจ็กต์แล้ว ออบเจ็กต์นั้นต้องสร้างโคลนที่มีโครงสร้างของออบเจ็กต์นั้นก่อน และกระบวนการโคลนที่มีโครงสร้างจะเกิดขึ้นในเทรดหลัก ยิ่งวัตถุมีขนาดใหญ่เท่าใด ระยะเวลาการบล็อกก็จะยิ่งนานขึ้นเท่านั้น

วิธีนี้ทำให้ต้องประสบปัญหาบางอย่างเมื่อวางแผนเกี่ยวกับวิธีคงสถานะแอปพลิเคชันกับ IndexedDB เนื่องจากไลบรารีการจัดการสถานะที่ได้รับความนิยมส่วนใหญ่ (เช่น Redux) ทำงานโดยการจัดการโครงสร้างสถานะทั้งหมดเป็นออบเจ็กต์ JavaScript รายการเดียว

การจัดการสถานะด้วยวิธีนี้มีประโยชน์หลายอย่าง และในขณะที่การจัดเก็บแผนผังทั้งสถานะเป็นระเบียนเดียวใน IndexedDB อาจเป็นเรื่องดึงดูดใจและสะดวก แต่การดำเนินการนี้หลังจากการเปลี่ยนแปลงทุกครั้ง (แม้ว่าจะมีการควบคุม/ลดระดับ) จะส่งผลให้เกิดการบล็อกเทรดหลักโดยไม่จำเป็น แต่จะเพิ่มโอกาสของข้อผิดพลาดในการเขียน และในบางกรณีอาจทำให้แท็บเบราว์เซอร์ขัดข้องหรือไม่ตอบสนองด้วย

คุณควรแบ่งต้นไม้สถานะออกเป็นระเบียนแต่ละรายการและอัปเดตเฉพาะระเบียนที่เปลี่ยนแปลงจริงๆ แทนที่จะจัดเก็บต้นไม้สถานะทั้งหมดไว้ในระเบียนเดียว

กฎข้อนี้ไม่ใช่กฎที่ห้ามทำในทุกกรณีเช่นเดียวกับแนวทางปฏิบัติแนะนำส่วนใหญ่ ในกรณีที่ไม่สามารถแยกออบเจ็กต์สถานะออกเป็นส่วนๆ และเขียนชุดการเปลี่ยนแปลงเพียงชุดเดียว การแยกข้อมูลออกเป็นต้นไม้ย่อยและเขียนเฉพาะข้อมูลเหล่านั้นยังคงดีกว่าการเขียนต้นไม้สถานะทั้งหมดเสมอ พัฒนาเพียงเล็กน้อย ย่อมดีกว่าไม่ปรับปรุงเลย

สุดท้าย คุณควรวัดผลกระทบด้านประสิทธิภาพของโค้ดที่คุณเขียนเสมอ แม้จะจริงอยู่ที่การเขียนขนาดเล็กไปยัง IndexedDB จะทำงานได้ดีกว่าการเขียนขนาดใหญ่ แต่จะมีความสำคัญก็ต่อเมื่อการเขียนไปยัง IndexedDB ที่แอปพลิเคชันทำอยู่จริงๆ ที่นำไปสู่งานที่ใช้เวลานาน ซึ่งจะบล็อกเทรดหลักและทำให้ประสบการณ์ของผู้ใช้แย่ลง คุณควรวัดผลเพื่อให้เข้าใจสิ่งที่เพิ่มประสิทธิภาพอยู่

สรุป

นักพัฒนาซอฟต์แวร์สามารถใช้กลไกพื้นที่เก็บข้อมูลไคลเอ็นต์ เช่น IndexedDB เพื่อปรับปรุงประสบการณ์การใช้งานแอปพลิเคชันของผู้ใช้ได้ ไม่เพียงแต่จะเก็บสถานะไว้ตลอดเซสชันเท่านั้น แต่ยังลดเวลาในการโหลดสถานะเริ่มต้นเมื่อเข้าชมซ้ำด้วย

แม้ว่าการใช้ IndexedDB อย่างเหมาะสมจะช่วยปรับปรุงประสบการณ์ของผู้ใช้ได้อย่างมาก แต่การใช้อย่างไม่ถูกต้องหรือไม่จัดการกับกรณีข้อผิดพลาดอาจทําให้แอปใช้งานไม่ได้และผู้ใช้ไม่พอใจ

เนื่องจากพื้นที่เก็บข้อมูลไคลเอ็นต์เกี่ยวข้องกับปัจจัยหลายอย่างที่ควบคุมไม่ได้ คุณจึงต้องทดสอบโค้ดอย่างละเอียดและจัดการข้อผิดพลาดอย่างเหมาะสม แม้กระทั่งข้อผิดพลาดที่ดูเหมือนจะไม่เกิดขึ้นในตอนแรก