Introdução à API Budget

A API Push Messaging permite enviar notificações a um usuário mesmo quando o navegador está fechado. Muitos desenvolvedores querem usar essas mensagens para atualizar e sincronizar conteúdo sem que o navegador esteja aberto, mas a API tem uma restrição importante: é necessário sempre exibir uma notificação para cada mensagem push recebida.

Ser capaz de enviar uma mensagem push para sincronizar dados no dispositivo de um usuário ou ocultar uma notificação mostrada anteriormente pode ser extremamente útil para usuários e desenvolvedores, mas permitir que um app da Web funcione em segundo plano sem que o usuário saiba está aberto a abusos.

A API Budget é uma nova API projetada para permitir que os desenvolvedores realizem trabalhos em segundo plano limitados sem notificar o usuário, como push silencioso ou uma busca em segundo plano. A partir do Chrome 60, você poderá começar a usar essa API, e a equipe do Chrome está ansiosa para receber feedback dos desenvolvedores.

Para permitir que os desenvolvedores consumam os recursos de um usuário em segundo plano, a plataforma da Web está introduzindo o conceito de orçamento usando a nova API orçamento. Cada site recebe uma quantidade de recursos com base no engajamento do usuário que pode consumir para ações em segundo plano, como um push silencioso, em que cada operação esgota o orçamento. Quando o orçamento é gasto, as ações em segundo plano não podem mais ser realizadas sem a visibilidade do usuário. O user agent será responsável por determinar o orçamento atribuído a um app da Web com base na heurística dele. Por exemplo, o subsídio de orçamento pode estar vinculado ao engajamento do usuário. Cada navegador pode decidir a própria heurística.

Texto longo, leia o resumo: a API orçamento permite reservar e usar um orçamento, acessar uma lista dos orçamentos restantes e entender os custos das operações em segundo plano.

Reservando orçamento

No Chrome 60 e versões mais recentes, o método navigator.budget.reserve() estará disponível sem nenhuma sinalização.

O método reserve() permite solicitar orçamento para uma operação específica e retorna um booleano para indicar se o orçamento pode ser reservado. Se o orçamento foi reservado, não é necessário notificar o usuário sobre o trabalho em segundo plano.

No exemplo de notificações push, é possível tentar reservar orçamento para uma operação "envio silencioso". Se reserve() for resolvido com "true", a operação será permitida. Caso contrário, a mensagem retorna "false", e você precisa mostrar uma notificação.

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);
});

No Chrome 60, o "push silencioso" é o único tipo de operação disponível, mas você pode encontrar uma lista completa de tipos de operação na especificação. Também não há uma maneira fácil de aumentar seu orçamento para fins de teste ou depuração depois de usado. No entanto, como uma solução temporária, você pode criar um novo perfil no Chrome. Infelizmente, não é possível usar a navegação anônima para isso, já que a API Budget retorna um orçamento igual a zero na navegação anônima (embora haja um bug que resulte em um erro durante meu teste).

Chame reserve() somente quando pretende executar a operação que está reservando em algum momento no futuro. Se você chamou a reserva no exemplo acima, mas ainda exibiu uma notificação, o orçamento ainda será usado.

Um caso de uso comum que não é ativado apenas pelo reserve() é a capacidade de programar um push silencioso de um back-end. A API orçamento tem APIs para permitir esse caso de uso, mas elas ainda estão sendo trabalhadas no Chrome e estão atualmente disponíveis apenas com sinalizações e / ou em um teste de origem.

API orçamento e testes de origem

Existem dois métodos, getBudget() e getCost(), que podem ser usados por um app da Web para planejar o uso do orçamento.

No Chrome 60, os dois métodos estarão disponíveis se você se inscrever no teste de origem. Caso contrário, é possível usá-los localmente ativando a sinalização de recursos da Plataforma Web experimental (Abra chrome://flags/#enable-experimental-web-platform-features no Chrome).

Vamos conferir como usar essas APIs.

Defina seu orçamento

Para saber qual é o orçamento disponível, use o método getBudget(). Alguns navegadores (como o Chrome) apresentam uma "declínio" de orçamento ao longo do tempo. Portanto, para dar visibilidade total, isso retorna uma matriz de BudgetStates, indicando qual será seu orçamento em vários momentos no futuro.

Para listar as entradas de orçamento que podemos gerar:

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

A primeira entrada será seu orçamento atual, e os valores adicionais mostrarão qual será seu orçamento em vários pontos no futuro.

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

Uma das vantagens de incluir futuras permissões de orçamento é que os desenvolvedores podem compartilhar essas informações com o back-end para adaptar o comportamento do lado do servidor, ou seja, enviar uma mensagem push para acionar uma atualização apenas quando o cliente tiver orçamento para um push silencioso.

Acessar o custo de uma operação

Para descobrir o custo de uma operação, chamar getCost() retornará um número indicando o valor máximo de orçamento que será consumido se você chamar reserve() para essa operação.

Por exemplo, podemos descobrir o custo de não mostrar uma notificação quando você recebe uma mensagem push (ou seja, o custo de um push silencioso) com o seguinte código:

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

No momento em que este artigo foi escrito, o Chrome 60 imprimirá:

Cost of silent push is: 2

Algo a destacar com os métodos reserve() e getCost() é que o custo real de uma operação pode ser menor que o custo retornado por getCost(). Ainda será possível reservar uma operação se o orçamento atual for menor que o custo indicado. Confira a seguir os detalhes específicos da especificação:

Essa é a API atual no Chrome e, como a Web continua a oferecer suporte a novas APIs que exigem a capacidade de realizar trabalhos em segundo plano, como a busca em segundo plano, a API orçamento pode ser usada para gerenciar o número de operações que podem ser realizadas sem notificar o usuário.

Enquanto você usa a API, envie feedback no repositório do GitHub (link em inglês) ou informe bugs do Chrome em crbug.com.