الطريقة الحديثة
تتيح لك المزامنة الدورية في الخلفية عرض محتوى جديد عند تشغيل تطبيق ويب تقدّمي أو خدمة صفحة مستندة إلى Worker. ويتم ذلك من خلال تنزيل البيانات في الخلفية عندما لا يكون التطبيق أو الصفحة قيد الاستخدام.
استخدام واجهة برمجة التطبيقات Periodic Background Sync API
بعد تثبيت مشغّل الخدمة، استخدِم Permissions API لإجراء طلب بحث عن periodic-background-sync
. ويمكنك إجراء ذلك من نافذة أو سياق عامل خدمة.
const status = await navigator.permissions.query({
name: 'periodic-background-sync',
});
if (status.state === 'granted') {
// Periodic background sync can be used.
} else {
// Periodic background sync cannot be used.
}
يتطلب تسجيل مزامنة دورية علامة والحد الأدنى من الفاصل الزمني للمزامنة
(minInterval
). وتحدِّد العلامة المزامنة المسجَّلة حتى يمكن تسجيل عمليات مزامنة متعددة. في
المثال أدناه، اسم العلامة هو 'content-sync'
وminInterval
هو يوم واحد.
navigator.serviceWorker.ready.then(async registration => {
try {
await registration.periodicSync.register('get-cats', { minInterval: 24 * 60 * 60 * 1000 });
console.log('Periodic background sync registered.');
} catch (err) {
console.error(err.name, err.message);
}
});
يُرجى الاتصال برقم periodicSync.getTags()
لاسترداد صفيف من علامات التسجيل. يستخدم المثال أدناه أسماء
العلامات للتأكّد من تفعيل تحديث ذاكرة التخزين المؤقت لتجنّب التحديث مرة أخرى.
const registration = await navigator.serviceWorker.ready;
if ('periodicSync' in registration) {
const tags = await registration.periodicSync.getTags();
// Only update content if sync isn't set up.
if (!tags.includes('content-sync')) {
updateContentOnPageLoad();
}
} else {
// If periodic background sync isn't supported, always update.
updateContentOnPageLoad();
}
للردّ على حدث مزامنة دورية في الخلفية، أضِف معالِج حدث periodicsync
إلى worker
الخدمة. وسيحتوي كائن الحدث الذي يتم تمريره على مَعلمة علامة تتطابق مع القيمة المستخدَمة أثناء
التسجيل. على سبيل المثال، إذا تم تسجيل عملية مزامنة منتظمة في الخلفية بالاسم
'content-sync'
، سيكون event.tag
هو 'content-sync'
.
self.addEventListener('periodicsync', (event) => {
if (event.tag === 'content-sync') {
event.waitUntil(syncContent());
}
});
توافُق المتصفح
الطريقة الكلاسيكية
بدلاً من تعديل البيانات في الخلفية لتكون جاهزة عندما يحمّل المستخدم التطبيق، تعتمد الطريقة الكلاسيكية ببساطة على تعديل البيانات عند التحميل.
مراجع إضافية
- تجارب أفضل بلا إنترنت باستخدام واجهة برمجة التطبيقات Periodic Background Sync API
- Web Periodic Background Synchronization API
عرض توضيحي
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link
rel="icon"
href=""
/>
<link rel="manifest" href="./manifest.json" />
<title>How to periodically synchronize data in the background</title>
<link rel="stylesheet" href="/style.css" />
<!-- TODO: Devsite - Removed inline handlers -->
<!-- <script src="/script.js" defer></script> -->
</head>
<body>
<h1>How to periodically synchronize data in the background</h1>
<p class="available">Periodic background sync can be used. Install the app first.</p>
<p class="not-available">Periodic background sync cannot be used.</p>
<h2>Last updated</h2>
<p class="last-updated">Never</p>
<h2>Registered tags</h2>
<ul>
<li>None yet.</li>
</ul>
</body>
</html>
html {
box-sizing: border-box;
font-family: system-ui, sans-serif;
color-scheme: dark light;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
margin: 1rem;
}
const available = document.querySelector('.available');
const notAvailable = document.querySelector('.not-available');
const ul = document.querySelector('ul');
const lastUpdated = document.querySelector('.last-updated');
const updateContent = async () => {
const data = await fetch(
'https://worldtimeapi.org/api/timezone/Europe/London.json'
).then((response) => response.json());
return new Date(data.unixtime * 1000);
};
const registerPeriodicBackgroundSync = async (registration) => {
const status = await navigator.permissions.query({
name: 'periodic-background-sync',
});
if (status.state === 'granted' && 'periodicSync' in registration) {
try {
// Register the periodic background sync.
await registration.periodicSync.register('content-sync', {
// An interval of one day.
minInterval: 24 * 60 * 60 * 1000,
});
available.hidden = false;
notAvailable.hidden = true;
// List registered periodic background sync tags.
const tags = await registration.periodicSync.getTags();
if (tags.length) {
ul.innerHTML = '';
}
tags.forEach((tag) => {
const li = document.createElement('li');
li.textContent = tag;
ul.append(li);
});
// Update the user interface with the last periodic background sync data.
const backgroundSyncCache = await caches.open('periodic-background-sync');
if (backgroundSyncCache) {
const backgroundSyncResponse =
backgroundSyncCache.match('/last-updated');
if (backgroundSyncResponse) {
lastUpdated.textContent = `${await fetch('/last-updated').then(
(response) => response.text()
)} (periodic background-sync)`;
}
}
// Listen for incoming periodic background sync messages.
navigator.serviceWorker.addEventListener('message', async (event) => {
if (event.data.tag === 'content-sync') {
lastUpdated.textContent = `${await updateContent()} (periodic background sync)`;
}
});
} catch (err) {
console.error(err.name, err.message);
available.hidden = true;
notAvailable.hidden = false;
lastUpdated.textContent = 'Never';
}
} else {
available.hidden = true;
notAvailable.hidden = false;
lastUpdated.textContent = `${await updateContent()} (manual)`;
}
};
if ('serviceWorker' in navigator) {
window.addEventListener('load', async () => {
const registration = await navigator.serviceWorker.register('./sw.js');
console.log('Service worker registered for scope', registration.scope);
await registerPeriodicBackgroundSync(registration);
});
}