ข้ามไปยังเนื้อหา

Periodic Background Sync

Periodic Background Sync (PBS) ช่วยให้ PWA ที่ install แล้วปลุก service worker ให้ทำงานตามกำหนดเวลาซ้ำๆ เพื่อรีเฟรชข้อมูล — แม้เมื่อผู้ใช้ไม่ได้ใช้แอปอยู่ เมื่อผู้ใช้เปิดแอปครั้งต่อไป พวกเขาจะเห็นเนื้อหาใหม่แทนที่จะเป็นข้อมูลเก่า

คิดว่าเป็น cron job ที่ทำงานภายใน browser โดยขึ้นอยู่กับ heuristics ของ browser เองว่าเมื่อไหรที่ปลอดภัยและเป็นประโยชน์ที่จะปลุกแอปของคุณ

sequenceDiagram
  participant App as Installed PWA
  participant SW as Service Worker
  participant Browser as Browser Scheduler
  participant Net as Network / API

  App->>SW: registration.periodicSync.register('refresh-news', { minInterval })
  Browser-->>SW: periodicsync event (browser decides timing)
  SW->>Net: fetch('/api/latest-articles')
  Net-->>SW: JSON response
  SW->>SW: caches.open('news').put(...)
  Note over App: User opens app — sees fresh content
Periodic Background Sync flow
async function checkPeriodicSyncSupport() {
if (!('periodicSync' in (await navigator.serviceWorker.ready))) {
console.warn('Periodic Background Sync is not supported');
return false;
}
const status = await navigator.permissions.query({ name: 'periodic-background-sync' });
console.log('Periodic sync permission:', status.state); // "granted", "denied", or "prompt"
return status.state === 'granted';
}
async function registerPeriodicSync() {
const registration = await navigator.serviceWorker.ready;
if (!('periodicSync' in registration)) return;
try {
await registration.periodicSync.register('refresh-news', {
minInterval: 24 * 60 * 60 * 1000, // 24 hours in milliseconds
});
console.log('Periodic sync registered');
} catch (err) {
console.warn('Periodic sync registration failed:', err);
}
}

minInterval เป็นเพียง hint — browser จะ fire event ไม่บ่อยกว่า interval นี้ แต่อาจ fire น้อยกว่าหรือไม่ fire เลยขึ้นอยู่กับ heuristics ของตัวเอง

// sw.js — service worker
self.addEventListener('periodicsync', (event) => {
if (event.tag === 'refresh-news') {
event.waitUntil(refreshNewsCache());
}
});
async function refreshNewsCache() {
const response = await fetch('/api/latest-articles');
if (!response.ok) return;
const cache = await caches.open('news-v1');
await cache.put('/api/latest-articles', response);
console.log('News cache refreshed at', new Date().toISOString());
}

event.waitUntil() ทำให้ SW ยังคงทำงานต่อจนกว่างาน async จะเสร็จสมบูรณ์ ถ้า fetch ของคุณใช้เวลานานเกินไปหรือล้มเหลว browser อาจไม่ retry ทันที

// List all registered periodic syncs
const registration = await navigator.serviceWorker.ready;
const tags = await registration.periodicSync.getTags();
console.log('Registered syncs:', tags);
// Unregister a specific sync
await registration.periodicSync.unregister('refresh-news');
ข้อจำกัดรายละเอียด
ต้อง install PWAPeriodic sync ต้องการให้แอปถูก install บน home screen หรือ desktop
เฉพาะ Chromiumณ ปี 2025 เฉพาะ browser ที่ใช้ Chromium เท่านั้นที่รองรับ PBS; Firefox และ Safari ไม่รองรับ
Browser กำหนด cadencebrowser ตัดสินใจ firing interval จริงตามแบตเตอรี่, เครือข่าย และ site engagement — ถือ minInterval เป็นค่าต่ำสุด ไม่ใช่ตาราง
ต้องมีเครือข่ายSW จะรัน handler เฉพาะเมื่ออุปกรณ์มีการเชื่อมต่อเครือข่าย
Engagement scoreChrome ติดตาม site engagement; เว็บไซต์ที่มี engagement ต่ำอาจมี PBS ถูก throttle หรือปิดใช้งาน
ต้องใช้ HTTPSเหมือนกับฟีเจอร์ service worker ทั้งหมด PBS ทำงานได้เฉพาะบน secure origins

เนื่องจาก browser ควบคุม cadence ออกแบบแอปให้ทำงานได้ถูกต้องแม้ periodicsync จะไม่ fire เลย:

  1. แสดงข้อมูลใน cache เสมอถ้า cache มีอยู่ — แม้ข้อมูลเก่าก็ดีกว่าหน้าจอว่างเปล่า
  2. รีเฟรชเมื่อเปิดหน้าเพจเป็น fallback เมื่อ periodic sync ไม่ได้ทำงาน
  3. แสดง timestamp “อัปเดตล่าสุด” เพื่อให้ผู้ใช้เข้าใจความสดของข้อมูล
// main.js — page code (fallback refresh on open)
async function loadArticles() {
const cache = await caches.open('news-v1');
const cached = await cache.match('/api/latest-articles');
if (cached) {
renderArticles(await cached.json());
// Still refresh in the background
fetch('/api/latest-articles').then(async (res) => {
if (res.ok) {
await cache.put('/api/latest-articles', res.clone());
renderArticles(await res.json());
}
});
} else {
const res = await fetch('/api/latest-articles');
const data = await res.json();
renderArticles(data);
}
}

บทเรียนแบบ code-only: Periodic Background Sync ต้องการ PWA ที่ install แล้วและมีเฉพาะใน browser ที่ใช้ Chromium ตัวอย่างด้านบนสมบูรณ์และถูกต้อง แต่ไม่สามารถรันใน in-browser playground ได้ ทดสอบใน Chrome หรือ Edge พร้อมกับ PWA ที่ install แล้ว

ตัวเลือกBenefitCost
Periodic Background Syncข้อมูลสดใหม่รอผู้ใช้อยู่แล้วตอนเปิดแอป โดยไม่ต้องรอโหลดต้องผ่านเกณฑ์ installed PWA + engagement heuristic ของ browser ก่อนถึงจะได้สิทธิ์ใช้
Sync ตอนเปิดแอปเท่านั้น (on-demand)ทำงานได้ทุก browser ไม่มีเงื่อนไขพิเศษผู้ใช้ต้องรอโหลดข้อมูลทุกครั้งที่เปิดแอป แม้เพิ่งเปิดไปเมื่อกี้
  • ตั้ง sync interval ถี่เกินไปโดยไม่สนใจว่า browser จะปรับ interval จริงตาม engagement ของผู้ใช้เองอยู่ดี (ตั้งเท่าไหร่ก็เป็นแค่ minimum)
  • ไม่ตรวจสิทธิ์ periodic-background-sync ก่อนเรียก register ทำให้โค้ด throw error บน browser ที่ยังไม่รองรับ
  • ใช้ periodic sync ดึงข้อมูลจำนวนมากโดยไม่สนใจ data usage ของผู้ใช้บนมือถือ ทำให้กิน quota โดยไม่รู้ตัว

💡 ตัวอย่างจากของจริง

Google Maps — ใช้ periodic sync อัปเดตข้อมูลจราจร/แผนที่ที่เคย cache ไว้ให้สดใหม่อยู่เสมอแม้ไม่ได้เปิดแอป

แอปข่าวหลายเจ้า — sync หัวข้อข่าวล่าสุดเบื้องหลังเป็นระยะ ให้พร้อมอ่านทันทีที่เปิดแอปโดยไม่ต้องรอโหลด

option minInterval ใน periodicSync.register() รับประกันอะไร?
ข้อใดจำเป็นสำหรับให้ Periodic Background Sync ทำงานได้?
event periodicsync ทำงานที่ไหน?
ทำไมจึงควรทำ fallback ที่ refresh ข้อมูลตอนโหลดหน้า?