Usar um service worker para gerenciar notificações

Kate Jeffreys
Kate Jeffreys

Neste codelab, você vai usar um worker de serviço para gerenciar notificações. As instruções aqui presumem que você já conhece os service workers e os conceitos básicos de solicitar permissão de notificação e enviar notificações. Se você precisar de uma revisão sobre notificações, consulte o codelab Primeiros passos com a API Notifications. Para saber mais sobre os service workers, consulte a Introdução aos service workers de Matt Gaunt.

Remixar o app de exemplo e acessá-lo em uma nova guia

As notificações são bloqueadas automaticamente pelo app Glitch incorporado. Por isso, não é possível visualizar o app nesta página. Em vez disso, faça o seguinte:

  1. Clique em Remix to Edit para tornar o projeto editável.
  2. Para visualizar o site, pressione View App. Em seguida, pressione Fullscreen tela cheia.

O Glitch vai abrir em uma nova guia do Chrome.

Ao trabalhar neste codelab, faça mudanças no código no Glitch incorporado nesta página. Atualize a nova guia com o app em tempo real para conferir as mudanças.

Conhecer o app de exemplo e o código inicial

Comece conferindo o app em tempo real na nova guia do Chrome:

  1. Pressione "Control+Shift+J" (ou "Command+Option+J" no Mac) para abrir as Ferramentas do desenvolvedor.
  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 rascunho de função que você vai implementar neste codelab.

Agora vamos conferir o código do app de exemplo no Glitch incorporado nesta página.

  1. No Glitch incorporado, confira public/index.js:

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

    • A função requestPermission solicita a permissão do 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 é 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 executa a detecção de recursos para o recurso do worker de serviço 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. No Glitch incorporado, 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 será executado quando o usuário clicar em Registrar service worker na interface do app. Esse código vai registrar public/service-worker.js como um service worker.

  1. No editor do Glitch incorporado, 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 tornar o processamento de promessas mais conveniente. 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 no 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 a referência ao registro do service worker.

  • Para concluir a funcionalidade de registro do worker de serviço, adicione um código para cancelar o registro do worker de serviço. 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á visualizando o app ativo, atualize a página. Os botões Registrar service worker e Cancelar inscrição do service worker 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 ele usando o método postMessage.

No editor Glitch incorporado, abra public/index.js e substitua a função sendNotification pelo seguinte código:

// 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 está fazendo:

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

  • O método postMessage do worker de serviço envia dados do app para o worker de serviço. 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+Reload). Consulte a documentação do controlador do ServiceWorker no MDN para mais informações.

Processar notificações no service worker

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

No editor do Glitch incorporado, 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 explicação rápida:

  • self é uma referência ao próprio service worker.

  • Embora o worker de serviço 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 processar esse erro de maneira mais suave.

Se você tiver problemas, acesse glitch.com/edit/#!/codelab-notifications-service-worker-completed para conferir o código completo.

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