| استراتيجية إدارة البيانات والتخزين المؤقت | آلية التشغيل البرمجي والخصائص | التأثير الهندسي على أداء التطبيق |
|---|---|---|
| الطلب المباشر بدون تخزين مؤقت (No Caching) | إرسال طلب جديد للسيرفر مع كل عملية تنقل أو تحديث للمكون دون حفظ البيانات محلياً | يستهلك موارد الشبكة ويزيد من وقت الاستجابة للمستخدم ويضغط على الخوادم |
| التخزين المؤقت الدائم (Static Caching) | حفظ البيانات لمرة واحدة في المتجر دون التحقق من صلاحيتها أو تاريخ تحديثها | سريع جداً في العرض ولكنه يعرض بيانات قديمة إن لم يتم تحديثها يدوياً |
| التخزين المؤقت الذكي مع الكيانات (Smart Entity Caching) | الاعتماد على معرفات فريدة (`IDs`) مع تتبع زمن الجلب (`lastFetched`) لإدارة الصلاحية والتحديث | يوازن بامتياز بين أداء العرض الفوري، تقليل طلبات الشبكة، وضمان حداثة البيانات المعروضة |
تعد إدارة مجموعات البيانات الكبيرة (Entities) والتخزين المؤقت (Caching) أمراً حاسماً لأداء التطبيقات الكبيرة. يوفر ملحق signalEntityState أو أدوات إدارة الكيانات في NgRx Signals بنية تحتية جاهزة ونظيفة للتعامل مع قوائم البيانات الضخمة (إضافة، تحديث، حذف، وبحث) دون كتابة أكواد مكررة، مما يضمن كفاءة استهلاك الذاكرة وسرعة استجابة واجهة المستخدم.
يتيح لك نظام كيانات NgRx Signals تنظيم البيانات على هيئة جدول قواميس داخلي (Dictionary) يعتمد على معرف فريد لكل عنصر، مما يجعل عمليات البحث والتحديث تتم في زمن قدره O(1) بدلاً من البحث التسلسلي البطء.
عبر تخزين البيانات المستلمة مسبقاً والتحقق من صلاحيتها، يتم تقليل طلبات الشبكة غير الضرورية، مما يرفع كفاءة التطبيق ويوفر تجربة استخدام فورية وسلسة للمستخدم النهائي.
| 1 | import { signalStore, withState, withMethods, patchState } from '@ngrx/signals'; |
| 2 | import { setEntities, addEntity, updateEntity, removeEntity, withEntities } from '@ngrx/signals/entities'; |
| 3 | |
| 4 | interface ItemEntity { |
| 5 | id: number; |
| 6 | name: string; |
| 7 | category: string; |
| 8 | } |
| 9 | |
| 10 | export const ItemEntityStore = signalStore( |
| 11 | { providedIn: 'root' }, |
| 12 | // تفعيل ممتص الكيانات المتقدم لإدارة القوائم بكفاءة |
| 13 | withEntities<ItemEntity>(), |
| 14 | withState({ |
| 15 | isLoading: false, |
| 16 | lastFetched: null as number | null |
| 17 | }), |
| 18 | withMethods((store) => ({ |
| 19 | // تخزين البيانات الأولية مع التخزين المؤقت |
| 20 | CacheInitialItems(items: ItemEntity[]) { |
| 21 | patchState(store, setEntities(items), { lastFetched: Date.now() }); |
| 22 | }, |
| 23 | // إضافة كيان جديد بسرعة فائقة |
| 24 | addNewItem(item: ItemEntity) { |
| 25 | patchState(store, addEntity(item)); |
| 26 | }, |
| 27 | // تحديث كيان موجود بناءً على معرفه الفريد |
| 28 | updateExistingItem(id: number, changes: Partial<ItemEntity>) { |
| 29 | patchState(store, updateEntity({ id, changes })); |
| 30 | }, |
| 31 | // حذف كيان من المجموعة |
| 32 | removeItem(id: number) { |
| 33 | patchState(store, removeEntity(id)); |
| 34 | } |
| 35 | })) |
| 36 | ); |
| 1 | <!-- entity-dashboard.component.html --> |
| 2 | <div class="entity-container"> |
| 3 | <h3>لوحة إدارة الكيانات والبيانات الكبيرة (NgRx Entity Signals)</h3> |
| 4 | |
| 5 | <div class="actions-bar"> |
| 6 | <button (click)="loadDemoData()" class="primary-btn">تحميل بيانات التخزين المؤقت</button> |
| 7 | <button (click)="addItem()" class="secondary-btn">إضافة عنصر للكيانات</button> |
| 8 | </div> |
| 9 | |
| 10 | <ul class="entity-list"> |
| 11 | @for (item of store.entities(); track item.id) { |
| 12 | <li class="entity-item"> |
| 13 | <span>{{ item.name }} ({{ item.category }})</span> |
| 14 | <div class="item-btns"> |
| 15 | <button (click)="updateItem(item.id)" class="edit-btn">تعديل</button> |
| 16 | <button (click)="deleteItem(item.id)" class="delete-btn">حذف</button> |
| 17 | </div> |
| 18 | </li> |
| 19 | } @empty { |
| 20 | <li>لا توجد كيانات مسجلة في المتجر حالياً</li> |
| 21 | } |
| 22 | </ul> |
| 23 | </div> |
⚠️ تحذير
تجنب تخزين البيانات الكبيرة بدون استراتيجية انتهاء صلاحية للتخزين المؤقت! ترك التخزين المؤقت (Caching) مفتوحاً بدون مراعاة زمن التحديث قد يؤدي إلى عرض بيانات قديمة للمستخدمين. احرص دائماً على ربط التخزين المؤقت بآليات إعادة جلب أو تحديث دورية عند الحاجة.