跳转到内容

用于更新的周期性后台同步:刷新内容 vs. 通知内容

一句话: 周期性后台同步让已安装 PWA 的 service worker 在后台周期性地刷新内容, 使应用在用户打开它时数据已经是最新的——这是一种静默更新,不同于推送通知那样面向用户的 可见提醒。

这两个 API 都运行在 service worker 中,都处理「有新东西」的问题,但承担不同的职责:

  • 周期性后台同步 按浏览器决定的时间表静默下载数据,使应用自身的界面在下次打开时是 最新的。它不产生通知,也不保证具体的运行时机。
  • 推送通知(通过 Push API)从服务端投递一条用于打断用户的消息,通常通过调用 showNotification() 来展示一条可见提醒。

常见做法是:将周期性后台同步用于常规内容刷新,把推送通知留给那些重要到值得打断用户 的更新——并不是每次周期性刷新都需要配套一条通知。

ServiceWorkerRegistration.periodicSync 暴露一个 PeriodicSyncManager

const registration = await navigator.serviceWorker.ready;
if ('periodicSync' in registration) {
try {
await registration.periodicSync.register('refresh-feed', {
minInterval: 24 * 60 * 60 * 1000,
});
} catch {
console.log('Periodic Sync could not be registered.');
}
}

在 service worker 中,periodicsync 处理器检查 event.tag 并刷新对应数据,只有在新 内容确实值得通知时才展示通知:

self.addEventListener('periodicsync', (event) => {
if (event.tag === 'refresh-feed') {
event.waitUntil(
refreshFeedCache().then((hasImportantUpdate) => {
if (hasImportantUpdate) {
return self.registration.showNotification('New content available');
}
})
);
}
});

MDN 将 PeriodicSyncManagerServiceWorkerRegistration.periodicSync 标记为实验性且 可用性有限,因为它们无法在一些最广泛使用的浏览器中运行。在生产环境中使用前,请仔细 检查浏览器兼容性数据。

根据 Chrome 的文档,周期性后台同步只对用户已安装并作为独立应用启动的 web 应用可用—— 它在普通浏览器标签页中不可用——并且访问权限还进一步受该已安装应用的用户使用度限制, 以避免很少被使用的安装在后台白白消耗电量或流量。

async function scheduleContentRefresh(tag, minInterval) {
const registration = await navigator.serviceWorker.ready;
if (!('periodicSync' in registration)) {
// 在此浏览器/上下文中不可用——回退到在页面加载时刷新,
// 而不是在后台刷新。
return false;
}
await registration.periodicSync.register(tag, { minInterval });
return true;
}
  • 在调用 register() 之前,先用 'periodicSync' in registration 做特性检测。
  • 只在已安装并已启动的 PWA 上依赖它——它在普通浏览器标签页中不可用。
  • 传入合理的 minInterval;实际的同步间隔不会短于该值,但浏览器可能会根据使用度 及其他信号让同步间隔更长。
  • 只在新内容确实值得打断用户时,才在 periodicsync 处理器中调用 showNotification()——不是每次后台刷新都需要。
  • 为周期性后台同步不可用的浏览器或上下文准备一个回退刷新路径(例如页面加载时 刷新)。