Budget API 简介

借助 Push Messaging API,即使浏览器关闭,我们也能向用户发送通知。许多开发者都希望能够在不打开浏览器的情况下使用此消息传递来更新和同步内容,但该 API 有一个重要限制:您收到的每条推送消息都必须显示一条通知。

能够发送推送消息以同步用户设备上的数据或隐藏您之前显示的通知,这对用户和开发者来说非常有用,但允许 Web 应用在后台工作,而用户不会知道存在滥用问题。

Budget API 是一个新的 API,它允许开发者在不通知用户的情况下执行有限的后台工作(如静默推送或执行后台提取)。在 Chrome 60 及更高版本中,您将可以开始使用此 API,Chrome 团队热切希望获得开发者的反馈。

为了让开发者能够在后台使用用户的资源,Web 平台引入了使用新的预算 API 的预算概念。系统会根据用户互动度为每个网站分配一定量的资源,这些资源可用于执行后台操作(例如静默推送),在此类情况下,每项操作都会耗尽预算。预算用尽后,在没有用户可见性的情况下,系统无法再执行后台操作。用户代理将负责根据 Web 应用的启发法确定分配给该应用的预算,例如预算限额可以与用户互动程度相关。每个浏览器都可以确定自己的启发式算法。

要点:通过预算 API,您可以预留预算、使用预算、获取剩余预算列表以及了解后台操作的费用

预留预算

在 Chrome 60 及更高版本中,navigator.budget.reserve() 方法将不带任何标志可用。

reserve() 方法允许您为特定操作请求预算,并且该方法会返回一个布尔值,指示是否可以预留该预算。如果预算已被预留,则无需通知用户您的后台工作。

在推送通知的示例中,您可以尝试为“静默推送”操作预留预算,如果 reserve() 解析为 true,则允许该操作。否则将返回 false,您需要显示通知

self.addEventListener('push', event => {
 const promiseChain = navigator.budget.reserve('silent-push')
   .then((reserved) => {
     if (reserved) {
       // No need to show a notification.
       return;
     }

     // Not enough budget is available, must show a notification.
     return registration.showNotification(...);
   });
 event.waitUntil(promiseChain);
});

在 Chrome 60 中,“silent-push”是唯一可用的操作类型,但您可以在规范中找到完整的操作类型列表。使用后,您无法轻松增加用于测试或调试的预算,但作为临时的解决方法,您可以在 Chrome 中创建新的配置文件。很遗憾,您无法使用无痕模式来实现此目的,因为在无痕模式下,Budget API 将返回零(尽管在测试期间有一个错误会导致出现错误)。

只有当您打算在未来的某个时间点执行预留的操作时,才应调用 reserve()。请注意,如果您在上述示例中调用了预留方式,但仍显示了通知,系统仍会使用预算。

从后端安排静默推送的功能是无法仅由 reserve() 启用的一个常见用例。Budget API 确实具有支持此用例的 API,但它们仍在 Chrome 中开发中,目前仅在标志和 / 或源试用后可用。

预算 API 和源试用

Web 应用可以使用两种方法(getBudget()getCost())规划其预算的使用。

在 Chrome 60 中,如果您申请参与源试用,就可以使用这两种方法;但如果是为了测试,您可以在本地使用这两个方法,只需启用实验性网络平台功能标志(在 Chrome 中打开 chrome://flags/#enable-experimental-web-platform-features)即可。

我们来看看如何使用这些 API。

获取您的预算

您可以使用 getBudget() 方法查找可用预算。某些浏览器(如 Chrome)会随着时间推移而出现预算“衰减”的情况,因此为了让您全面了解情况,此 API 会返回一个 BudgetStates 数组,表示您的预算在未来各个时间的具体金额。

如需列出预算条目,我们可以运行以下命令:

navigator.budget.getBudget()
.then((budgets) => {
  budgets.forEach((element) => {
    console.log(\`At '${new Date(element.time).toString()}' \` +
      \`your budget will be '${element.budgetAt}'.\`);
  });
});

第一个条目是您当前的预算,其他值将显示未来各个时间点的预算金额。

At 'Mon Jun 05 2017 12:47:20' you will have a budget of '3'.
At 'Fri Jun 09 2017 10:42:57' you will have a budget of '2'.
At 'Fri Jun 09 2017 12:31:09' you will have a budget of '1'.

添加未来预算限额的一个好处是,开发者可以与其后端共享此信息,以调整其服务器端行为(即,仅在客户端有预算来进行静默推送时,才发送推送消息以触发更新)。

获取操作费用

为了确定某项操作的费用,调用 getCost() 将返回一个数字,指示如果您针对该操作调用 reserve() 将会消耗的最大预算金额。

例如,我们可以用以下代码找出在收到推送消息时不显示通知的开销(即静默推送的开销):

navigator.budget.getCost('silent-push')
.then((cost) => {
  console.log('Cost of silent push is:', cost);
})
.catch((err) => {
  console.error('Unable to get cost:', err);
});

在撰写本文时,Chrome 60 将输出以下内容:

Cost of silent push is: 2

reserve()getCost() 方法需要强调的一点是,操作的实际费用可以低于 getCost() 返回的费用。如果当前预算低于所示费用,您仍然可以预留操作。该规范的具体详细信息如下:

这是 Chrome 中当前的 API,随着网络继续支持需要能够执行后台工作(例如后台提取)的新 API,Budget API 可用于管理您可以在不通知用户的情况下执行的操作数量。

当您使用该 API 时,请在 GitHub 代码库中提供反馈,或在 crbug.com 上提交 Chrome bug。