Usar um service worker para gerenciar notificações

Kate Jeffreys
Kate Jeffreys

Neste codelab, você usará um service worker 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 ativo para conferir as mudanças.

Conhecer o app de exemplo e o código inicial

Comece conferindo o aplicativo publicado 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 Informações está selecionada na lista suspensa Níveis, ao lado da caixa Filtro.

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

    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 realiza a detecção de recursos para o 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. 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 worker de serviço 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 uma 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 houver. Isso facilita a referência ao registro do service worker.

  • Para concluir a funcionalidade de registro do service worker, adicione o código para cancelar o registro do service worker. Substitua a função unRegisterServiceWorker por este 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 registro de service worker agora devem estar funcionando.

Enviar notificações para o service worker

Nesta etapa, você vai criar 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 do Glitch incorporado, abra public/index.js e substitua a função sendNotification por este 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);
 
});
});

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