اكتشف مدير المزامنة الدورية للواجهة الأمامية، وهو نهج شامل لإدارة المهام الخلفية، وتحسين الأداء، وتعزيز تجربة المستخدم في تطبيقات الويب الحديثة. تعرف على أفضل الممارسات وأمثلة من العالم الحقيقي.
مدير المزامنة الدورية للواجهة الأمامية: إتقان تنسيق المهام الخلفية
في عالم تطوير الويب الديناميكي، يعتبر ضمان تجارب المستخدم السلسة أمرًا بالغ الأهمية. غالبًا ما تتطلب تطبيقات الويب الحديثة إجراء مهام خلفية، مثل مزامنة البيانات وتحديثات المحتوى والإشعارات المجدولة، دون مقاطعة سير عمل المستخدم. يوفر مدير المزامنة الدورية للواجهة الأمامية حلاً قويًا لتنسيق هذه المهام الخلفية بكفاءة وفعالية. يستكشف هذا الدليل الشامل مفهوم المزامنة الدورية وفوائدها واستراتيجيات التنفيذ وأفضل الممارسات لبناء تطبيقات ويب عالية الأداء.
فهم المزامنة الدورية
تسمح المزامنة الدورية لتطبيقات الويب، وخاصة تطبيقات الويب التقدمية (PWAs)، بمزامنة البيانات في الخلفية على فترات منتظمة. هذه القدرة ضرورية للحفاظ على محتوى محدث، وتوفير وظائف دون اتصال بالإنترنت، وتقديم تجربة مستخدم سريعة الاستجابة، حتى في البيئات ذات الاتصال الشبكي المتقطع. تتيح واجهة برمجة تطبيقات المزامنة الخلفية الدورية، وهي جزء من مجموعة واجهة برمجة تطبيقات عامل الخدمة، للمطورين جدولة المهام التي تعمل بشكل مستقل عن سلسلة التعليمات الرئيسية، مما يضمن الحد الأدنى من التأثير على أداء التطبيق.
فوائد المزامنة الدورية
- تحسين تجربة المستخدم: حافظ على المحتوى جديدًا وذا صلة، مما يوفر للمستخدمين أحدث المعلومات دون تحديثات يدوية.
- وظائف دون اتصال بالإنترنت: تمكين المستخدمين من الوصول إلى البيانات المخزنة مؤقتًا والتفاعل معها، حتى في حالة عدم الاتصال بالإنترنت، مما يعزز سهولة استخدام التطبيق في ظروف الشبكة المختلفة.
- أداء مُحسَّن: قم بتفريغ مزامنة البيانات والمهام الأخرى كثيفة الاستخدام للموارد إلى الخلفية، مما يقلل الحمل على سلسلة التعليمات الرئيسية ويحسن الاستجابة الشاملة للتطبيق.
- تقليل استخدام البيانات: قم بتحسين مزامنة البيانات عن طريق نقل التحديثات الضرورية فقط، مما يقلل من استهلاك النطاق الترددي والتكاليف المرتبطة به.
- زيادة التفاعل: قم بتسليم الإشعارات والتحديثات في الوقت المناسب، مع إبقاء المستخدمين على اطلاع دائم ومتفاعلين مع التطبيق.
تنفيذ مدير المزامنة الدورية للواجهة الأمامية
يتضمن تنفيذ مدير المزامنة الدورية للواجهة الأمامية عدة خطوات رئيسية، بما في ذلك تسجيل عامل خدمة، وطلب الأذونات، وجدولة أحداث المزامنة الدورية، والتعامل مع عملية المزامنة. فيما يلي إرشادات تفصيلية وأمثلة التعليمات البرمجية لإرشادك خلال عملية التنفيذ.
الخطوة 1: تسجيل عامل خدمة
الخطوة الأولى هي تسجيل عامل خدمة، والذي يعمل كوكيل بين تطبيق الويب والشبكة. يعترض عامل الخدمة طلبات الشبكة، ويخزن الأصول مؤقتًا، ويتعامل مع المهام الخلفية. لتسجيل عامل خدمة، أضف التعليمات البرمجية التالية إلى ملف JavaScript الرئيسي الخاص بك:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(registration => {
console.log('Service Worker registered with scope:', registration.scope);
})
.catch(error => {
console.error('Service Worker registration failed:', error);
});
}
الخطوة 2: طلب الأذونات
قبل جدولة أحداث المزامنة الدورية، تحتاج إلى طلب الأذونات اللازمة من المستخدم. يسمح إذن `periodicSync` لعامل الخدمة بتنفيذ مهام المزامنة الخلفية. أضف التعليمات البرمجية التالية إلى ملف عامل الخدمة الخاص بك:
self.addEventListener('activate', async event => {
try {
const status = await navigator.permissions.query({ name: 'periodic-background-sync' });
if (status.state === 'granted') {
console.log('Periodic Background Sync permission granted.');
} else {
console.warn('Periodic Background Sync permission not granted.');
}
} catch (error) {
console.error('Error querying Periodic Background Sync permission:', error);
}
});
الخطوة 3: جدولة أحداث المزامنة الدورية
بمجرد حصولك على الأذونات اللازمة، يمكنك جدولة أحداث المزامنة الدورية باستخدام طريقة `register` الخاصة بكائن `periodicSync`. تأخذ هذه الطريقة اسم علامة فريدًا وكائن خيارات اختياري يحدد الحد الأدنى للفاصل الزمني بين أحداث المزامنة. أضف التعليمات البرمجية التالية إلى ملف عامل الخدمة الخاص بك:
self.addEventListener('activate', async event => {
// ... (previous permission check)
try {
await self.registration.periodicSync.register('content-sync', {
minInterval: 24 * 60 * 60 * 1000, // 24 hours
});
console.log('Periodic Sync registered successfully with tag: content-sync');
} catch (error) {
console.error('Error registering Periodic Sync:', error);
}
});
في هذا المثال، يتم استخدام العلامة `content-sync` لتحديد حدث المزامنة الدورية، ويتم تعيين الخيار `minInterval` على 24 ساعة، مما يضمن تشغيل مهمة المزامنة مرة واحدة على الأقل في اليوم.
الخطوة 4: التعامل مع عملية المزامنة
عندما يتم تشغيل حدث مزامنة دوري، يتلقى عامل الخدمة حدث `periodicsync`. يمكنك التعامل مع هذا الحدث عن طريق إضافة مستمع حدث إلى ملف عامل الخدمة الخاص بك. داخل مستمع الحدث، يمكنك تنفيذ مهام المزامنة الضرورية، مثل جلب البيانات من الخادم وتحديث ذاكرة التخزين المؤقت وعرض الإشعارات.
self.addEventListener('periodicsync', event => {
if (event.tag === 'content-sync') {
event.waitUntil(syncContent());
}
});
async function syncContent() {
try {
const response = await fetch('/api/content');
const content = await response.json();
// Store content in cache (e.g., using Cache API or IndexedDB)
const cache = await caches.open('content-cache');
await cache.put('/content-data', new Response(JSON.stringify(content)));
console.log('Content synchronized successfully.');
// Optional: Display a notification to the user
self.registration.showNotification('Content Updated', {
body: 'New content is available!',
icon: '/icon.png'
});
} catch (error) {
console.error('Error synchronizing content:', error);
// Handle error (e.g., retry later)
}
}
في هذا المثال، تجلب الدالة `syncContent` أحدث محتوى من الخادم، وتخزنه في ذاكرة التخزين المؤقت، وتعرض إشعارًا للمستخدم. تضمن طريقة `event.waitUntil` بقاء عامل الخدمة نشطًا حتى تكتمل مهمة المزامنة.
أفضل الممارسات لمدير المزامنة الدورية للواجهة الأمامية
لتحقيق أقصى قدر من فعالية مدير المزامنة الدورية للواجهة الأمامية، ضع في اعتبارك أفضل الممارسات التالية:
- تحسين مزامنة البيانات: قلل من كمية البيانات المنقولة أثناء المزامنة عن طريق جلب التحديثات الضرورية فقط واستخدام تقنيات ضغط البيانات الفعالة.
- تنفيذ معالجة الأخطاء: قم بتنفيذ معالجة قوية للأخطاء للتعامل بأمان مع أخطاء الشبكة وأخطاء الخادم والمشكلات غير المتوقعة الأخرى. استخدم آليات إعادة المحاولة واستراتيجيات التراجع الأسي لضمان نجاح مهام المزامنة في النهاية.
- احترام تفضيلات المستخدم: اسمح للمستخدمين بالتحكم في تكرار وتوقيت مهام المزامنة. توفير خيارات لتعطيل المزامنة الدورية أو تعديل فاصل المزامنة بناءً على تفضيلاتهم.
- مراقبة الأداء: راقب أداء مدير المزامنة الدورية للواجهة الأمامية لتحديد ومعالجة أي اختناقات في الأداء. استخدم أدوات مطوري المتصفح ومنصات التحليلات لتتبع أوقات المزامنة ومعدلات الخطأ واستهلاك الموارد.
- الاختبار بدقة: اختبر مدير المزامنة الدورية للواجهة الأمامية في ظروف شبكة مختلفة، بما في ذلك البيئات غير المتصلة بالإنترنت، للتأكد من أنه يعمل بشكل صحيح ويوفر تجربة مستخدم سلسة.
- مراعاة عمر البطارية: كن حذرًا بشأن استهلاك البطارية، خاصة على الأجهزة المحمولة. تجنب فواصل المزامنة المتكررة التي يمكن أن تستنزف البطارية بسرعة.
التقنيات والاعتبارات المتقدمة
استخدام واجهة برمجة تطبيقات الجلب في الخلفية
لتنزيل الملفات أو الأصول الكبيرة في الخلفية، ضع في اعتبارك استخدام واجهة برمجة تطبيقات الجلب في الخلفية. تتيح لك واجهة برمجة التطبيقات هذه بدء عمليات التنزيل وإدارتها في الخلفية، حتى عندما يغلق المستخدم المتصفح أو ينتقل بعيدًا عن الصفحة. توفر واجهة برمجة تطبيقات الجلب في الخلفية تحديثات التقدم والإشعارات، مما يسمح لك بإبقاء المستخدمين على اطلاع دائم بحالة التنزيل.
التكامل مع إشعارات الدفع
اجمع بين المزامنة الدورية وإشعارات الدفع لتقديم تحديثات وإشعارات في الوقت المناسب للمستخدمين، حتى عندما لا يكون التطبيق قيد التشغيل في المقدمة. استخدم المزامنة الدورية للتحقق من وجود محتوى أو تحديثات جديدة ثم قم بتشغيل إشعار دفع لتنبيه المستخدم. كن حذرًا بشأن تفضيلات المستخدم وتجنب إرسال إشعارات مفرطة أو غير ذات صلة.
التعامل مع تعارضات البيانات
عند مزامنة البيانات بين العميل والخادم، من المهم التعامل مع تعارضات البيانات المحتملة. قم بتنفيذ استراتيجيات حل التعارضات، مثل آخر كتابة تفوز أو التأمين المتفائل، لضمان اتساق البيانات وسلامتها. توفير آليات للمستخدمين لحل النزاعات يدويًا إذا لزم الأمر.
التدويل والترجمة
عند تطوير تطبيقات لجمهور عالمي، ضع في اعتبارك التدويل والترجمة. تأكد من أن مدير المزامنة الدورية للواجهة الأمامية يدعم لغات ومناطق متعددة. استخدم ملفات الموارد أو خدمات الترجمة لتوفير محتوى وإشعارات مترجمة.
مثال: التعامل مع المناطق الزمنية في الجدولة عند جدولة المهام الحساسة للوقت، من الضروري مراعاة المناطق الزمنية المختلفة. يتمثل الحل البسيط في تخزين جميع الأوقات بتوقيت UTC وتحويلها إلى التوقيت المحلي للمستخدم داخل التطبيق. يمكن لكائن JavaScript `Date`، جنبًا إلى جنب مع مكتبات مثل Moment.js أو date-fns، تسهيل عمليات التحويل هذه.
// Store the scheduled time in UTC
const scheduledTimeUTC = '2024-10-27T10:00:00Z';
// Convert to the user's local time
const scheduledTimeLocal = moment.utc(scheduledTimeUTC).local().format('YYYY-MM-DD HH:mm:ss');
console.log('Scheduled Time (UTC):', scheduledTimeUTC);
console.log('Scheduled Time (Local):', scheduledTimeLocal);
يوضح هذا المقتطف كيفية استخدام Moment.js لتحويل وقت UTC إلى التوقيت المحلي للمستخدم، مما يضمن تنفيذ المهام المجدولة في الوقت الصحيح بغض النظر عن موقع المستخدم. ضع في اعتبارك استخدام طرق مماثلة في تطبيق المزامنة الدورية للتعامل مع التحديثات الحساسة للوقت بدقة.
أمثلة من العالم الحقيقي
تطبيق مُجمِّع الأخبار
يمكن لتطبيق مُجمِّع الأخبار استخدام مدير المزامنة الدورية للواجهة الأمامية لمزامنة أحدث المقالات الإخبارية من مصادر مختلفة في الخلفية. يمكن للتطبيق جدولة أحداث المزامنة الدورية لجلب مقالات جديدة وتحديث ذاكرة التخزين المؤقت، مما يضمن وصول المستخدمين دائمًا إلى أحدث الأخبار، حتى في حالة عدم الاتصال بالإنترنت. يمكن استخدام إشعارات الدفع لتنبيه المستخدمين عند توفر مقالات جديدة.
تطبيق التجارة الإلكترونية
يمكن لتطبيق التجارة الإلكترونية استخدام مدير المزامنة الدورية للواجهة الأمامية لمزامنة كتالوجات المنتجات والأسعار ومستويات المخزون في الخلفية. يمكن للتطبيق جدولة أحداث المزامنة الدورية لجلب أحدث بيانات المنتج وتحديث ذاكرة التخزين المؤقت، مما يضمن وصول المستخدمين دائمًا إلى معلومات المنتج الدقيقة. يمكن استخدام إشعارات الدفع لتنبيه المستخدمين عند إضافة منتجات جديدة أو عند تخفيض الأسعار.
تطبيق الوسائط الاجتماعية
يمكن لتطبيق الوسائط الاجتماعية استخدام مدير المزامنة الدورية للواجهة الأمامية لمزامنة المنشورات والتعليقات والإعجابات الجديدة في الخلفية. يمكن للتطبيق جدولة أحداث المزامنة الدورية لجلب أحدث بيانات الوسائط الاجتماعية وتحديث ذاكرة التخزين المؤقت، مما يضمن وصول المستخدمين دائمًا إلى أحدث المحتوى. يمكن استخدام إشعارات الدفع لتنبيه المستخدمين عندما يتلقون تعليقات أو إعجابات جديدة.
تطبيق إدارة المهام
يمكن لتطبيق إدارة المهام، الذي تستخدمه فرق منتشرة في جميع أنحاء العالم، الاستفادة من المزامنة الدورية لضمان تحديث قوائم المهام دائمًا. على سبيل المثال، يكمل أحد أعضاء الفريق في طوكيو مهمة في الساعة 9:00 صباحًا بتوقيت اليابان. يضمن مدير المزامنة الدورية أن ينعكس هذا التحديث على أجهزة أعضاء الفريق في لندن ونيويورك وسيدني في غضون فترة زمنية معقولة، مع مراعاة ظروف الشبكة المختلفة. يمكن تعديل تردد المزامنة بناءً على نشاط المستخدم أو توفر الشبكة لتحسين استخدام البطارية واستهلاك البيانات.
الأدوات والمكتبات
- Workbox: مجموعة من المكتبات والأدوات التي تبسط تطوير PWAs، بما في ذلك عمال الخدمة والمزامنة الدورية. يوفر Workbox واجهات برمجة تطبيقات وتجريدات عالية المستوى تسهل إدارة التخزين المؤقت والتوجيه والمهام الخلفية.
- PWA Builder: أداة تساعدك على تحويل تطبيق الويب الحالي إلى PWA. يقوم PWA Builder تلقائيًا بإنشاء عامل خدمة وملف بيان ويوفر إرشادات حول تنفيذ أفضل الممارسات لـ PWAs.
- Lighthouse: أداة تدقيق تحلل الأداء وإمكانية الوصول و SEO لتطبيق الويب الخاص بك. يقدم Lighthouse توصيات لتحسين جودة وأداء تطبيقك.
خاتمة
يعد مدير المزامنة الدورية للواجهة الأمامية أداة قوية لبناء تطبيقات ويب عالية الأداء توفر تجربة مستخدم سلسة، حتى في البيئات ذات الاتصال الشبكي المتقطع. من خلال تنفيذ المزامنة الدورية، يمكنك الحفاظ على المحتوى جديدًا وذا صلة، وتوفير وظائف دون اتصال بالإنترنت، وتعزيز الاستجابة الشاملة للتطبيق. باتباع أفضل الممارسات الموضحة في هذا الدليل، يمكنك تحقيق أقصى قدر من فعالية مدير المزامنة الدورية للواجهة الأمامية وتقديم تجارب مستخدم استثنائية لجمهورك العالمي.باختصار، مدير المزامنة الدورية للواجهة الأمامية ليس مجرد تطبيق تقني؛ إنه نهج استراتيجي لتعزيز مشاركة المستخدم وتوفير دعم دون اتصال بالإنترنت وتحسين استخدام البيانات. من خلال فهم مبادئه وتطبيق أفضل الممارسات، يمكن للمطورين إنشاء تطبيقات ويب عالمية حقيقية تلقى صدى لدى المستخدمين في جميع أنحاء العالم.
الأسئلة الشائعة
ماذا يحدث إذا لم يمنح المستخدم إذن periodic-background-sync؟
إذا لم يمنح المستخدم الإذن، فستطرح طريقة `register` خطأً. يجب عليك التعامل مع هذا الخطأ بأمان، وإبلاغ المستخدم بأن الميزة لن تعمل بدون الإذن وربما تقديم إرشادات حول كيفية منحها في إعدادات المتصفح الخاص به.
كم مرة يجب أن أجدول أحداث المزامنة الدورية؟
يعتمد تكرار أحداث المزامنة على المتطلبات المحددة لتطبيقك وأهمية تحديث البيانات. ضع في اعتبارك التأثير على عمر البطارية واستخدام البيانات. ابدأ بفاصل زمني أطول (على سبيل المثال، 24 ساعة) وقلله تدريجيًا حسب الحاجة، مع مراقبة الأداء وتعليقات المستخدمين. تذكر أن `minInterval` هو *الحد الأدنى* - قد يقوم المتصفح بالمزامنة بشكل أقل تكرارًا بناءً على نشاط المستخدم وظروف الجهاز.
هل يمكنني استخدام المزامنة الدورية بدون عامل خدمة؟
لا، المزامنة الدورية هي ميزة في واجهة برمجة تطبيقات عامل الخدمة وتتطلب تسجيل عامل خدمة وتفعيله.
كيف تختلف المزامنة الدورية عن الجلب في الخلفية؟
تم تصميم المزامنة الدورية لمزامنة البيانات على فترات منتظمة، بينما تم تصميم الجلب في الخلفية لتنزيل الملفات أو الأصول الكبيرة في الخلفية. تُستخدم المزامنة الدورية عادةً للحفاظ على تحديث المحتوى، بينما يُستخدم الجلب في الخلفية لتنزيل الموارد التي سيحتاجها المستخدم لاحقًا.
هل المزامنة الدورية مدعومة من قبل جميع المتصفحات؟
لا يزال دعم المزامنة الدورية قيد التطور. في حين أنه مدعوم من قبل معظم المتصفحات الحديثة (Chrome و Edge و Firefox و Safari)، فقد لا تدعمه المتصفحات القديمة أو تلك التي لديها إعدادات خصوصية محددة بشكل كامل. تحقق دائمًا من توافق المتصفح الحالي قبل تنفيذ المزامنة الدورية في تطبيقك. يجب استخدام تقنيات التحسين التدريجي لتوفير آلية احتياطية للمتصفحات التي لا تدعم واجهة برمجة التطبيقات.
كيف يمكنني اختبار وظائف المزامنة الدورية؟
يمكنك اختبار وظائف المزامنة الدورية باستخدام أدوات مطوري المتصفح. في Chrome، على سبيل المثال، يمكنك استخدام لوحة التطبيق لتشغيل حدث مزامنة دوري يدويًا أو محاكاة ظروف شبكة مختلفة. تتيح لك علامة التبويب Service Workers فحص حالة عامل الخدمة ومراقبة نشاطه.
ما هي الآثار الأمنية لاستخدام المزامنة الدورية؟
مثل أي واجهة برمجة تطبيقات ويب، فإن للمزامنة الدورية آثارًا أمنية محتملة. تأكد من أنك تقوم فقط بمزامنة البيانات من مصادر موثوقة وأنك تستخدم بروتوكولات اتصال آمنة (HTTPS). كن حذرًا بشأن خصوصية البيانات وامتثل للوائح ذات الصلة، مثل GDPR و CCPA.
كيف يحدد المتصفح متى يقوم بالمزامنة فعليًا؟
يتمتع المتصفح بحرية كبيرة في تحديد *متى* يتم إجراء المزامنة فعليًا، حتى إذا تم تحديد `minInterval`. يعتمد هذا على عوامل مثل: نشاط المستخدم، واتصال الشبكة، وحالة البطارية، وما إذا كان الموقع قد تم التفاعل معه مؤخرًا. يحاول المتصفح تحسين تردد المزامنة لتحقيق أفضل توازن بين الأداء وعمر البطارية وتجربة المستخدم. لا يمكنك *ضمان* حدوث المزامنة بالضبط في الفاصل الزمني المحدد، فقط أنها لن تحدث *في وقت أقرب*.
ما هي بدائل المزامنة الدورية إذا كنت بحاجة إلى مزيد من التحكم؟
في حين أن المزامنة الدورية توفر الراحة، فقد تحتاج إلى مزيد من التحكم في سيناريوهات معينة. تشمل البدائل:
- WebSockets: للاتصال في الوقت الفعلي ثنائي الاتجاه بين العميل والخادم. مثالي للتطبيقات التي تحتاج إلى تحديثات فورية.
- Server-Sent Events (SSE): للتحديثات أحادية الاتجاه (من الخادم إلى العميل). أبسط من WebSockets للسيناريوهات التي لا يحتاج فيها العميل إلى إرسال البيانات مرة أخرى.
- Background Tasks (using dedicated workers): يمكنك إنشاء Web Worker مخصص أو Shared Worker يقوم بمهام مستقلة عن Service Worker أو سلسلة التعليمات الرئيسية. يسمح هذا بجدولة عمليات خلفية مخصصة، ولكنه يتطلب تنفيذًا أكثر تعقيدًا.
- Combination of APIs: يمكن أن يمنح الجمع بين واجهات برمجة التطبيقات الأبسط مثل `fetch` مع أدوات جدولة التحكم الدقيق.
كيف تتعامل المزامنة الدورية مع أنواع الأجهزة المختلفة (سطح المكتب مقابل الهاتف المحمول)؟
يتعامل تنفيذ المتصفح الأساسي مع الاختلافات بين أجهزة سطح المكتب والأجهزة المحمولة. بالنسبة للأجهزة المحمولة، سيكون المتصفح أكثر عدوانية في الحفاظ على البطارية وعرض النطاق الترددي. لذلك، قد تكون المزامنات الدورية أقل تكرارًا على الأجهزة المحمولة مقارنة بأجهزة سطح المكتب. ضع ذلك في الاعتبار عند تصميم تطبيقك واختر ترددات المزامنة المناسبة لكلا النوعين من الأجهزة. يعد الاختبار على كلا النوعين من الأجهزة أمرًا بالغ الأهمية.
مثال: المزامنة الدورية مع شريط التقدم
للإشارة إلى المستخدم بأنه تتم مزامنة المحتوى، يمكنك عرض شريط تقدم. إليك مثال بسيط:
self.addEventListener('periodicsync', event => {
if (event.tag === 'content-sync') {
event.waitUntil(syncContent());
}
});
async function syncContent() {
try {
// Show progress bar
showProgressBar();
const response = await fetch('/api/content');
const total = response.headers.get('Content-Length');
let loaded = 0;
const reader = response.body.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
loaded += value.length;
const progress = loaded / total;
updateProgressBar(progress);
// Process the data (example: cache the chunk)
// ...
}
// Hide progress bar
hideProgressBar();
} catch (error) {
console.error('Error synchronizing content:', error);
// Handle error (e.g., retry later)
hideProgressBar();
}
}
ملاحظة: يجب تحديد الوظائف `showProgressBar()` و `updateProgressBar(progress)` و `hideProgressBar()` بشكل منفصل في تطبيقك (على الأرجح في البرنامج النصي الرئيسي). يتيح استخدام `response.body.getReader()` القراءة التدريجية للبيانات وتحديث مؤشر التقدم.