Usar um service worker para gerenciar notificações

Kate Jeffreys
Kate Jeffreys

Neste codelab, você vai usar um service worker para gerenciar notificações. As instruções aqui pressupõem que você já esteja familiarizado com service workers e os princípios básicos de solicitação de permissão de notificação e envio de notificações. Se você precisar relembrar as notificações, consulte o codelab Começar a usar a API Notifications. Para saber mais sobre service workers, consulte a Introdução aos service workers de Matt Gaunt.

Conhecer o app de exemplo e o código inicial

Comece observando o app ativo na nova guia do Chrome:

  1. Pressione "Control+Shift+J" (ou "Command+Option+J" no Mac) para abrir o DevTools.
  2. Clique na guia Console.

  3. Verifique se a opção Info está selecionada no menu suspenso Levels ao lado da caixa Filter.

  4. No console do DevTools do app ativo, você vai encontrar uma mensagem:

    TODO: Implement getRegistration().

    Esta é uma mensagem de um stub de função que você vai implementar neste codelab.

Agora vamos analisar o código do app de exemplo.

  1. Confira public/index.js:

    • Há quatro stubs para as funções que você vai implementar: registerServiceWorker, getRegistration, unRegisterServiceWorker e sendNotification.

    • A função requestPermission pede permissão ao usuário para enviar notificações. Se você fez o codelab "Começar a usar a API Notifications", vai notar que a função requestPermission dele é usada aqui. A única diferença é que agora ele também atualiza a interface do usuário depois de resolver a solicitação de permissão.

    • A função updateUI atualiza todos os botões e mensagens do app.

    • A função initializePage realiza a detecção de recursos para a capacidade do service worker no navegador e atualiza a interface do usuário do app.

    • O script aguarda até que a página seja carregada e a inicializa.

  2. Abra public/service-worker.js.

    Como o nome sugere, você vai adicionar código ao app para registrar esse arquivo como um service worker.

    Embora o arquivo ainda não esteja em uso pelo app, ele contém um código inicial que vai imprimir uma mensagem no console quando o service worker for ativado.

    Você vai adicionar código a public/service-worker.js para processar notificações quando o service worker as receber.

Registrar o service worker

Nesta etapa, você vai escrever um código que é executado quando o usuário clica em Registrar service worker na interface do app. Esse código vai registrar public/service-worker.js como um service worker.

  1. Abra public/index.js. Substitua a função registerServiceWorker pelo seguinte código:

    // Use the Service Worker API to register a service worker.
    async function registerServiceWorker() {
      await navigator.serviceWorker.register('./service-worker.js')
      updateUI();
    }
    

    O registerServiceWorker usa a declaração async function para facilitar o processamento de promessas. Isso permite await o valor resolvido de um Promise. Por exemplo, a função acima aguarda o resultado do registro de um service worker antes de atualizar a interface. Consulte await na MDN para mais informações.

  2. Agora que o usuário pode registrar um service worker, você pode receber uma referência ao objeto de registro do service worker. Em public/index.js, substitua a função getRegistration pelo seguinte código:

    // Get the current service worker registration.
    function getRegistration() {
      return navigator.serviceWorker.getRegistration();
    }
    

    A função acima usa a API Service Worker para receber o registro atual do service worker, se ele existir. Isso facilita um pouco mais a obtenção de uma referência ao registro do service worker.

  • Para concluir a funcionalidade de registro do service worker, adicione um código para cancelar o registro dele. Substitua a função unRegisterServiceWorker pelo seguinte código:

    // Unregister a service worker, then update the UI.
    async function unRegisterServiceWorker() {
      // Get a reference to the service worker registration.
      let registration = await getRegistration();
      // Await the outcome of the unregistration attempt
      // so that the UI update is not superceded by a
      // returning Promise.
      await registration.unregister();
      updateUI();
    }
    

Na guia em que você está vendo o app ativo, atualize a página. Os botões Registrar service worker e Cancelar inscrição do service worker agora devem estar funcionando.

Enviar notificações para o service worker

Nesta etapa, você vai escrever um código que será executado quando o usuário clicar em Enviar uma notificação na interface do app. Esse código vai criar uma notificação, verificar se um service worker está registrado e enviar a notificação para o service worker usando o método postMessage.

Abra public/index.js e substitua a função sendNotification pelo código a seguir:

// Create and send a test notification to the service worker.
async function sendNotification() {
  // Use a random number as part of the notification data
  // (so you can tell the notifications apart during testing!)
  let randy = Math.floor(Math.random() * 100);
  let notification = {
    title: 'Test ' + randy,
    options: { body: 'Test body ' + randy }
  };
  // Get a reference to the service worker registration.
  let registration = await getRegistration();
  // Check that the service worker registration exists.
  if (registration) {
    // Check that a service worker controller exists before
    // trying to access the postMessage method.
    if (navigator.serviceWorker.controller) {
      navigator.serviceWorker.controller.postMessage(notification);
    } else {
      console.log('No service worker controller found. Try a soft reload.');
    }
  }
}

Confira o que esse código faz:

  • sendNotification é uma função assíncrona. Portanto, você pode usar await para receber uma referência ao registro do service worker.

  • O método postMessage do service worker envia dados do app para o service worker. Consulte a documentação do MDN sobre postMessage para mais informações.

  • O código verifica a presença da propriedade navigator.serviceWorker.controller antes de tentar acessar a função postMessage. navigator.serviceWorker.controller será null se não houver um service worker ativo ou se a página tiver sido atualizada à força (Shift+Recarregar). Consulte a documentação do controlador ServiceWorker na MDN para mais informações.

Processar notificações no service worker

Nesta etapa, você vai escrever um código no service worker que processa as mensagens postadas nele e mostra notificações ao usuário.

Abra public/service-worker.js. Adicione o seguinte código ao final do arquivo:

// Show notification when received
self.addEventListener('message', (event) => {
  let notification = event.data;
  self.registration.showNotification(
    notification.title,
    notification.options
  ).catch((error) => {
    console.log(error);
  });
});

Confira uma breve explicação:

  • self é uma referência ao service worker.

  • Embora o service worker agora lide com a exibição de notificações, a interface principal do app ainda é responsável por receber a permissão de notificação do usuário. Se a permissão não for concedida, a promessa retornada por showNotification será rejeitada. O código acima usa um bloco catch para evitar um erro de rejeição Promise não detectado e lidar com ele de maneira um pouco mais elegante.

Continue para o próximo codelab desta série: Criar um servidor de notificações push.