أفضل الممارسات للحفاظ على حالة التطبيق باستخدام IndexedDB

تعرَّف على أفضل الممارسات لمزامنة حالة التطبيق بين IndexedDB ومكتبات إدارة الحالة الشائعة.

عندما يحمّل المستخدِم موقعًا إلكترونيًا أو تطبيقًا لأول مرة، غالبًا ما يتطلّب ذلك قدرًا لا بأس به من العمل لإنشاء حالة التطبيق الأولية التي يتم استخدامها لمحاولة عرض واجهة المستخدم. على سبيل المثال، يحتاج التطبيق أحيانًا إلى مصادقة المستخدم من جهة العميل ثم تقديم عدة طلبات لواجهة برمجة التطبيقات قبل الحصول على كل البيانات التي يحتاج إلى عرضها على الصفحة.

يمكن أن يكون تخزين حالة التطبيق في IndexedDB طريقة رائعة لتسريع وقت التحميل لعمليات التحميل المتكرّرة. يمكن للتطبيق بعد ذلك المزامنة مع أي خدمات واجهة برمجة تطبيقات في الخلفية وتعديل واجهة المستخدم بالبيانات الجديدة بشكلٍ بطيء، باستخدام استراتيجية إعادة التحقّق من صحة البيانات أثناء عدم توفّرها.

ومع ذلك، عند استخدام IndexedDB، هناك العديد من الأمور المهمة التي يجب مراعاتها والتي قد لا تكون واضحة على الفور للمطوّرين المبتدئين في واجهات برمجة التطبيقات. يجيب هذا المستند عن الأسئلة الشائعة ويناقش بعض أهم الأمور التي يجب مراعاتها عند الاحتفاظ بحالة التطبيق في IndexedDB.

الحفاظ على سلوك التطبيق المتوقّع

تعود الكثير من التعقيدات المتعلقة بـ IndexedDB إلى حقيقة أنّ هناك العديد من العوامل التي لا يمكنك (المطوّر) التحكّم فيها. يتناول هذا القسم العديد من المشاكل التي يجب أخذها في الاعتبار عند العمل مع IndexedDB.

قد يتعذّر إجراء عمليات الكتابة في مساحة التخزين

يمكن أن تحدث أخطاء عند الكتابة إلى IndexedDB لأسباب مختلفة، وفي بعض الحالات تكون هذه الأسباب خارج نطاق سيطرتك كمطوّر. على سبيل المثال، لا تسمح بعض المتصفّحات بكتابة البيانات في IndexedDB عند استخدام وضع التصفّح المتخفي. هناك أيضًا احتمال أن يستخدم أحد المستخدمين جهازًا أوشكت فيه مساحة القرص على النفاد، وسيحظر عليه المتصفّح تخزين أي محتوى على الإطلاق.

لهذا السبب، من المهم جدًا تنفيذ معالجة أخطاء مناسبة في رمز IndexedDB دائمًا. ويعني ذلك أيضًا أنّه من الجيد بشكل عام الحفاظ على حالة التطبيق في الذاكرة (بالإضافة إلى تخزينها)، حتى لا تتعطل واجهة المستخدم عند تشغيلها في وضع التصفّح بخصوصية تامّة أو عندما لا تكون مساحة التخزين متوفّرة (حتى إذا لم تعمل بعض ميزات التطبيق الأخرى التي تتطلّب مساحة تخزين).

قد يكون المستخدم قد عدّل البيانات المخزّنة أو حذفها.

على عكس قواعد البيانات من جهة الخادم التي يمكنك فيها حظر الوصول غير المصرّح به، يمكن لأدوات المطوّرين وإضافات المتصفّح الوصول إلى قواعد البيانات من جهة العميل، ويمكن للمستخدم محو هذه البيانات.

على الرغم من أنّه من غير الشائع أن يعدّل المستخدمون بياناتهم المخزّنة على الجهاز، إلا أنّه من الشائع جدًا أن يُفرِغوها. من المهم أن يتمكّن تطبيقك من التعامل مع كلتا الحالتَين بدون حدوث خطأ.

قد تكون البيانات المخزَّنة قديمة

على غرار القسم السابق، حتى إذا لم يعدّل المستخدم البيانات بنفسه، من الممكن أيضًا أن تكون البيانات المتوفّرة لديه في مساحة التخزين قد تم إنشاؤها باستخدام إصدار سابق من الرمز البرمجي، وربما كان هذا الإصدار يتضمّن أخطاء.

يتوفّر في IndexedDB دعم مضمّن لإصدارات المخطط والترقية باستخدام IDBOpenDBRequest.onupgradeneeded()، ومع ذلك، عليك كتابة رمز الترقية بطريقة تتيح للمستخدم التعامل مع الإصدار السابق (بما في ذلك الإصدار الذي يتضمّن خطأ).

يمكن أن تكون اختبارات الوحدة مفيدة جدًا في هذا الشأن، لأنّه غالبًا ما يكون من غير الممكن اختبار جميع مسارات الترقية والحالات المحتملة يدويًا.

الحفاظ على أداء تطبيقك

من الميزات الرئيسية لواجهة برمجة التطبيقات IndexedDB هي واجهة برمجة التطبيقات غير المتزامنة، ولكن لا تعتقد أنّه ليس عليك القلق بشأن الأداء عند استخدامها. هناك عدد من الحالات التي قد يؤدي فيها الاستخدام غير الصحيح إلى حظر السلسلة الرئيسية، ما قد يؤدي إلى عدم الاستجابة.

بوجه عام، يجب ألا تكون عمليات القراءة والكتابة في IndexedDB أكبر من المقدار المطلوب للبيانات التي يتم الوصول إليها.

على الرغم من أنّ IndexedDB تتيح تخزين عناصر كبيرة ومتداخلة كسجلّ واحد (وإنّ إجراء ذلك ملائم جدًا من وجهة نظر المطوّر)، يجب تجنُّب هذه الممارسة. والسبب في ذلك هو أنّه عندما يخزِّن IndexedDB عنصرًا، يجب أولاً إنشاء نسخة مفصّلة من هذا العنصر، و تتم عملية النسخ المفصّل في الخيط الرئيسي. كلما زاد حجم الجسم، زاد وقت الحظر.

يطرح ذلك بعض التحديات عند التخطيط لكيفية الاحتفاظ بحالة التطبيق في IndexedDB، لأنّ معظم مكتبات إدارة الحالة الشائعة (مثل Redux) تعمل من خلال إدارة شجرة الحالة بالكامل كأحد عناصر JavaScript.

على الرغم من أنّ إدارة الحالة بهذه الطريقة لها العديد من المزايا، وعلى الرغم من أنّ تخزين شجرة الحالة بالكامل كسجلّ واحد في IndexedDB قد يكون مغريًا و مناسبًا، فإنّ إجراء ذلك بعد كل تغيير (حتى إذا تمّ تقييد السرعة أو إيقاف الربط المؤقت) يؤدي إلى حظر غير ضروري للسلسلة الرئيسية، وسيزيد من احتمالية حدوث أخطاء في الكتابة، وفي بعض الحالات قد يؤدي ذلك إلى تعطُّل علامة تبويب المتصفّح أو توقُّفها عن الاستجابة.

بدلاً من تخزين شجرة الحالات بأكملها في سجلّ واحد، يجب تقسيمها إلى سجلّات فردية وتعديل السجلات التي تتغيّر فقط.

وكما هو الحال مع معظم أفضل الممارسات، هذه ليست قاعدة مطلقة. في الحالات التي لا يكون فيها من الممكن تقسيم عنصر حالة وكتابة مجموعة التغيُّرات الأساسية فقط، يبقى تقسيم البيانات إلى أشجار فرعية وكتابتها فقط هو الخيار المفضَّل مقارنةً بكتابة شجرة الحالة بأكملها في كل مرة. إنّ إجراء تحسينات بسيطة هو أفضل من عدم إجراء أي تحسينات على الإطلاق.

أخيرًا، يجب دائمًا قياس تأثير الأداء للرمز الذي تكتبه. على الرغم من أنّه من الصحيح أنّ عمليات الكتابة الصغيرة إلى IndexedDB ستحقق أداءً أفضل من عمليات الكتابة الكبيرة، لا يهمّ ذلك إلا إذا كانت عمليات الكتابة التي يجريها تطبيقك إلى IndexedDB تؤدي في الواقع إلى مهام طويلة تحظر سلسلة المهام الرئيسية وتؤدي إلى خفض مستوى تجربة المستخدم. من المهم قياس الأداء لكي تعرف ما تريد تحسينه.

الاستنتاجات

يمكن للمطوّرين استخدام آليات تخزين العميل، مثل IndexedDB، لتحسين تجربة المستخدم في تطبيقاتهم من خلال الاحتفاظ بالحالة على مستوى الجلسات فقط، ولكن أيضًا من خلال تقليل الوقت المستغرَق لتحميل الحالة الأولية عند الزيارات المتكرّرة.

على الرغم من أنّ استخدام IndexedDB بشكل صحيح يمكن أن يحسّن تجربة المستخدم بشكل كبير، إلا أنّ استخدامه بشكل غير صحيح أو عدم معالجة حالات الخطأ يمكن أن يؤدي إلى تعطُّل التطبيقات وعدم رضا المستخدمين.

بما أنّ مساحة التخزين في الجهاز تعتمد على العديد من العوامل الخارجة عن نطاق سيطرتك، من المهّم اختبار التعليمات البرمجية جيدًا والتعامل مع الأخطاء بشكل صحيح، حتى تلك التي قد تبدو في البداية غير محتملة الحدوث.