Cara modern
Dengan sinkronisasi latar belakang berkala, Anda dapat menampilkan konten baru saat progressive web app atau halaman yang didukung pekerja layanan diluncurkan. Hal ini dilakukan dengan mendownload data di latar belakang saat aplikasi atau halaman tidak digunakan.
Menggunakan Periodic Background Sync API
Setelah pekerja layanan diinstal, gunakan
Permissions API untuk membuat kueri
periodic-background-sync
. Anda bisa melakukannya dari jendela atau konteks pekerja layanan.
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.
}
Mendaftarkan sinkronisasi berkala memerlukan tag dan interval sinkronisasi minimum
(minInterval
). Tag mengidentifikasi sinkronisasi terdaftar sehingga beberapa sinkronisasi dapat didaftarkan. Pada contoh di bawah, nama tag adalah 'content-sync'
dan minInterval
adalah satu hari.
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);
}
});
Panggil periodicSync.getTags()
untuk mengambil array tag pendaftaran. Contoh di bawah ini menggunakan nama tag untuk mengonfirmasi bahwa pembaruan cache aktif untuk menghindari pembaruan lagi.
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();
}
Untuk merespons peristiwa sinkronisasi latar belakang berkala, tambahkan pengendali peristiwa periodicsync
ke pekerja layanan Anda. Objek peristiwa yang diteruskan ke objek tersebut akan berisi parameter tag yang cocok dengan nilai yang digunakan selama pendaftaran. Misalnya, jika sinkronisasi latar belakang berkala didaftarkan dengan nama
'content-sync'
, event.tag
akan menjadi 'content-sync'
.
self.addEventListener('periodicsync', (event) => {
if (event.tag === 'content-sync') {
event.waitUntil(syncContent());
}
});
Kompatibilitas browser
Cara klasik
Daripada memperbarui data di latar belakang agar siap saat pengguna memuat aplikasi, cara klasik hanya terdiri dari mengupdate data saat dimuat.
Bacaan lebih lanjut
- Pengalaman offline yang lebih kaya dengan Periodic Background Sync API
- API Sinkronisasi Latar Belakang Berkala Web
Demo
HTML
<!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>
CSS
html {
box-sizing: border-box;
font-family: system-ui, sans-serif;
color-scheme: dark light;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
margin: 1rem;
}
JS
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);
});
}