通过 Periodic Background Sync API 获得更丰富的离线体验

在后台同步 Web 应用的数据,提供更接近应用的体验

Joe Medley
Joe Medley

您是否遇到过以下任何情况?

  • 乘坐火车或地铁,但网络连接不稳定或无法连接
  • 因观看了太多视频而被运营商限制
  • 生活在带宽无法跟上需求的国家/地区

如果是,那么您肯定会在网络上处理某些事情时感到沮丧,并且想知道为什么平台专用应用在这些情况下通常表现更好。平台专用应用可以提前提取最新内容,例如新闻报道或天气信息。即使地铁没有网络,您仍然可以阅读新闻。

通过定期后台同步,Web 应用能够在后台定期同步数据,使 Web 应用的行为更接近平台特有应用的行为。

试用

您可以尝试通过实时演示应用定期进行后台同步。在使用该应用之前,请确保:

  • 您使用的是 Chrome 80 或更高版本。
  • 您需要先安装 Web 应用,然后再启用定期后台同步。

概念和用法

通过定期后台同步,您可以在渐进式 Web 应用或由 Service Worker 支持的页面启动时显示新内容。为此,它会在未使用应用或网页时在后台下载数据。这可以防止应用内容在用户查看期间在启动后刷新。更好的是,它可防止应用在刷新之前显示内容旋转图标。

如果没有定期后台同步,Web 应用必须使用其他方法下载数据。一个常见的示例是使用推送通知来唤醒 Service Worker。用户被“有新数据可用”等消息打断。更新数据本质上是一种副作用。您仍然可以选择使用推送通知来发布真正重要的更新,例如重大重大新闻。

定期后台同步很容易与后台同步混淆。虽然它们的名称相似,但使用场景有所不同。除此之外,后台同步最常用于在之前的请求失败时将数据重新发送至服务器。

确保用户互动度正确

如果操作不当,定期进行后台同步可能会浪费用户的资源。在发布此版本之前,Chrome 对其进行了试用期,以确保其正确无误。本部分介绍了 Chrome 为尽可能提高此功能的实用性采取的一些设计决策。

Chrome 作出的第一个设计决策是,只有在用户已在其设备上安装 Web 应用并将其作为不同的应用启动后,该应用才能使用定期后台同步。在 Chrome 的常规标签页中,无法使用定期后台同步。

此外,由于 Chrome 不希望未使用或很少使用的 Web 应用无故消耗电池电量或数据,因此 Chrome 设计了定期后台同步功能,因此开发者必须为用户提供价值,才能实现后台同步。具体而言,Chrome 使用网站互动得分 (about://site-engagement/) 来确定给定 Web 应用是否可定期执行后台同步以及同步频率。换言之,除非互动得分大于零,否则 periodicsync 事件根本不会触发,并且其值会影响 periodicsync 事件的触发频率。这样可以确保只有您正在使用的应用才在后台同步。

定期后台同步与常用平台上的现有 API 和做法有一些相似之处。例如,通过一次性后台同步和推送通知,在用户关闭页面后,Web 应用的逻辑的存在时间会延长(通过其 Service Worker)。在大多数平台上,用户都会安装定期在后台访问网络的应用,以便为关键更新、预提取内容、同步数据等提供更好的用户体验。同样,定期后台同步还会延长 Web 应用逻辑的生命周期,使其定期运行,一次可能只需几分钟。

如果浏览器允许这种行为频繁且不受限制,则可能会导致一些隐私问题。Chrome 采用如下方式应对这种定期后台同步风险:

  • 后台同步活动只会在设备先前连接的网络上发生。Chrome 建议仅连接到可信方运营的网络。
  • 与所有互联网通信一样,定期后台同步会显示客户端的 IP 地址、正在连接的服务器以及服务器的名称。为了将这种风险降低到应用仅在前台运行时同步的大致情况,浏览器限制了应用的后台同步频率,使其与用户使用该应用的频率保持一致。如果用户停止频繁与该应用互动,定期后台同步将停止触发。这是对平台专用应用的现状的净改进。

什么情况下可以使用?

使用规则因浏览器而异。综上所述,Chrome 对定期后台同步提出了以下要求:

  • 特定的用户互动度得分。
  • 之前使用过的网络。

同步的时间不受开发者控制。同步频率将与应用的使用频率一致。(请注意,平台专用应用目前不执行此操作。)它还会考虑设备的电源和连接状态。

应在何时使用该功能?

当您的 Service Worker 醒来处理 periodicsync 事件时,您有机会请求数据,但没有义务这样做。处理事件时,您应考虑网络条件和可用存储空间,并下载不同数量的数据作为响应。您可以通过以下资源获取帮助:

权限

安装 Service Worker 后,使用 Permissions API 查询 periodic-background-sync。您可以通过窗口或 Service Worker 上下文执行此操作。

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.
}

注册定期同步

如前所述,定期后台同步需要一个 Service Worker。使用 ServiceWorkerRegistration.periodicSync 检索 PeriodicSyncManager,并对其调用 register()。注册需要一个标记和一个最小同步间隔 (minInterval)。该标记用于标识已注册的同步,以便可以注册多次同步。在以下示例中,标记名称为 'content-sync'minInterval 为一天。

const registration = await navigator.serviceWorker.ready;
if ('periodicSync' in registration) {
  try {
    await registration.periodicSync.register('content-sync', {
      // An interval of one day.
      minInterval: 24 * 60 * 60 * 1000,
    });
  } catch (error) {
    // Periodic background sync cannot be used.
  }
}

验证注册

调用 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();
}

您还可以使用 getTags() 在 Web 应用的设置页面中显示有效注册的列表,以便用户可以启用或停用特定类型的更新。

响应定期的后台同步事件

如需响应定期的后台同步事件,请向您的 Service Worker 添加 periodicsync 事件处理脚本。传递给它的 event 对象将包含一个与注册期间使用的值匹配的 tag 参数。例如,如果使用名称 'content-sync' 注册了定期的后台同步,则 event.tag 将为 'content-sync'

self.addEventListener('periodicsync', (event) => {
  if (event.tag === 'content-sync') {
    // See the "Think before you sync" section for
    // checks you could perform before syncing.
    event.waitUntil(syncContent());
  }
  // Other logic for different tags as needed.
});

取消注册同步

如需结束已注册的同步,请使用您要取消注册的同步名称调用 periodicSync.unregister()

const registration = await navigator.serviceWorker.ready;
if ('periodicSync' in registration) {
  await registration.periodicSync.unregister('content-sync');
}

接口

下面简要介绍了 Periodic Background Sync API 提供的接口。

  • PeriodicSyncEvent。在浏览器选择时传递给 ServiceWorkerGlobalScope.onperiodicsync 事件处理脚本。
  • PeriodicSyncManager:注册和取消注册定期同步,并为已注册的同步提供标记。从 ServiceWorkerRegistration.periodicSync` 属性检索此类的实例。
  • ServiceWorkerGlobalScope.onperiodicsync:注册一个处理程序以接收 PeriodicSyncEvent
  • ServiceWorkerRegistration.periodicSync:返回对 PeriodicSyncManager 的引用。

示例

更新内容

以下示例使用定期后台同步为新闻网站或博客下载并缓存最新报道。请注意标记名称,它表示同步的种类 ('update-articles')。对 updateArticles() 的调用封装在 event.waitUntil() 中,这样 Service Worker 不会在文章下载和存储之前终止。

async function updateArticles() {
  const articlesCache = await caches.open('articles');
  await articlesCache.add('/api/articles');
}

self.addEventListener('periodicsync', (event) => {
  if (event.tag === 'update-articles') {
    event.waitUntil(updateArticles());
  }
});

定期向现有 Web 应用添加后台同步

如需向现有 PWA 添加定期后台同步,需要进行这组更改。此示例包含许多有用的日志记录语句,这些语句描述了 Web 应用中定期后台同步的状态。

调试

在本地测试时获取定期后台同步的端到端视图可能并非易事。活跃注册数、大致同步间隔和过往同步事件日志的相关信息可在调试 Web 应用的行为时提供有价值的背景信息。幸运的是,您可以通过 Chrome 开发者工具中的实验性功能找到所有这些信息。

记录本地活动

开发者工具的定期后台同步部分围绕定期后台同步生命周期内的关键事件进行组织:注册同步、执行后台同步和取消注册。如需获取有关这些事件的信息,请点击 Start recording

开发者工具中的记录按钮
开发者工具中的“记录”按钮

在记录过程中,系统会在开发者工具中显示与事件对应的条目,并记录每个事件的上下文和元数据。

记录的定期后台同步数据示例
已记录的定期后台同步数据示例

启用一次录制功能后,录制状态最长可保持启用三天,这让开发者工具可以捕获有关可能发生的后台同步的本地调试信息,甚至是数小时后的时间。

模拟活动

虽然记录后台活动可能很有帮助,但有时,您可能希望立即测试 periodicsync 处理程序,而不是等待事件按其正常频率触发。

您可以通过 Chrome DevTools 的 Application 面板中的 Service Workers 部分执行此操作。通过定期同步字段,您可以提供要使用的事件代码,并根据需要触发该事件。

Application 面板的“Service Workers”部分显示“Periodic Sync”文本字段和按钮。

使用开发者工具界面

从 Chrome 81 开始,您将在开发者工具的应用面板中看到定期后台同步部分。

显示“定期后台同步”部分的“应用程序”面板