Até agora, abordamos a inscrição de um usuário e o envio de uma mensagem push. A próxima etapa é receber essa mensagem push no dispositivo do usuário e mostrar uma notificação (assim como qualquer outro trabalho que possamos querer fazer).
O evento push
Quando uma mensagem é recebida, um evento push é enviado no service worker.
O código para configurar um listener de eventos push precisa ser bastante semelhante a qualquer outro listener de eventos que você escreveria em JavaScript:
self.addEventListener('push', function(event) {
if (event.data) {
console.log('This push event has data: ', event.data.text());
} else {
console.log('This push event has no data.');
}
});
A parte mais estranha desse código para a maioria dos desenvolvedores que são novos nos service workers é a variável
self
. self
é comumente usado nos Web Workers, que são um service worker. self
refere-se ao
escopo global, como window
em uma página da Web. Mas, para workers da Web e service workers,
self
se refere ao worker em si.
No exemplo acima, self.addEventListener()
pode ser considerado como a adição de um listener de eventos ao
próprio service worker.
No exemplo do evento push, verificamos se há algum dado e imprimimos algo no console.
Há outras maneiras de analisar os dados de um evento push:
// Returns string
event.data.text()
// Parses data as JSON string and returns an Object
event.data.json()
// Returns blob of data
event.data.blob()
// Returns an arrayBuffer
event.data.arrayBuffer()
A maioria das pessoas usa json()
ou text()
dependendo do que espera do aplicativo.
Este exemplo demonstra como adicionar um listener de eventos de push e como acessar dados, mas faltam duas funções muito importantes. Ele não mostra uma notificação e não
usa event.waitUntil()
.
Esperar até
Uma das coisas a entender sobre os service workers é que você tem pouco controle sobre quando
o código do service worker será executado. O navegador decide quando ativá-lo e quando encerrá-lo. A única maneira de dizer ao navegador: "Ei, estou muito ocupado fazendo coisas
importantes" é transmitindo uma promessa para o método event.waitUntil()
. Com isso, o navegador
vai manter o service worker em execução até que a promessa transmitida seja resolvida.
Com eventos push, há um requisito adicional de exibir uma notificação antes que a promessa transmitida seja resolvida.
Confira um exemplo básico de exibição de uma notificação:
self.addEventListener('push', function(event) {
const promiseChain = self.registration.showNotification('Hello, World.');
event.waitUntil(promiseChain);
});
A chamada self.registration.showNotification()
é o método que mostra uma notificação para
o usuário e retorna uma promessa que será resolvida quando a notificação for exibida.
Para manter este exemplo o mais claro possível, atribuí essa promessa a uma
variável chamada promiseChain
. Depois, ela é transmitida para event.waitUntil()
. Sei que isso é
muito detalhado, mas já vi vários problemas que culminaram em
um mal-entendido sobre o que precisa ser transmitido para waitUntil()
ou como resultado de cadeias de
promessas quebradas.
Um exemplo mais complicado com uma solicitação de rede para dados e rastreamento do evento push com análise pode ser parecido com este:
self.addEventListener('push', function(event) {
const analyticsPromise = pushReceivedTracking();
const pushInfoPromise = fetch('/api/get-more-data')
.then(function(response) {
return response.json();
})
.then(function(response) {
const title = response.data.userName + ' says...';
const message = response.data.message;
return self.registration.showNotification(title, {
body: message
});
});
const promiseChain = Promise.all([
analyticsPromise,
pushInfoPromise
]);
event.waitUntil(promiseChain);
});
Aqui, estamos chamando uma função que retorna uma promessa pushReceivedTracking()
,
que, para fins de exemplo, podemos fingir que fará uma solicitação de rede
para nosso provedor de análise. Também fazemos uma solicitação de rede, recebemos a
resposta e mostramos uma notificação usando os dados de respostas para o título e
a mensagem da notificação.
Podemos garantir que o service worker permaneça ativo enquanto ambas as tarefas são feitas combinando
essas promessas com Promise.all()
. A promessa resultante é transmitida para event.waitUntil()
,
o que significa que o navegador aguardará até que as duas promessas sejam concluídas antes de verificar se uma notificação
foi exibida e encerrar o service worker.
O motivo pelo qual precisamos nos preocupar com waitUntil()
e como usá-lo é que um dos problemas mais comuns que os desenvolvedores enfrentam é que, quando a cadeia de promessas está incorreta ou quebrada, o Chrome mostra esta notificação "padrão":
O Chrome só vai mostrar a notificação "Este site foi atualizado em segundo plano" quando uma
mensagem push for recebida e o evento push no worker do serviço não mostrar uma
notificação depois que a promessa transmitida para event.waitUntil()
for concluída.
O principal motivo pelo qual os desenvolvedores são pegos é que o código
muitas vezes chama self.registration.showNotification()
, mas não faz
nada com a promessa que ele retorna. Isso faz com que a notificação padrão seja mostrada
intermittentemente. Por exemplo, poderíamos remover o retorno de
self.registration.showNotification()
no exemplo acima e correr o risco de ver esta
notificação.
self.addEventListener('push', function(event) {
const analyticsPromise = pushReceivedTracking();
const pushInfoPromise = fetch('/api/get-more-data')
.then(function(response) {
return response.json();
})
.then(function(response) {
const title = response.data.userName + ' says...';
const message = response.data.message;
self.registration.showNotification(title, {
body: message
});
});
const promiseChain = Promise.all([
analyticsPromise,
pushInfoPromise
]);
event.waitUntil(promiseChain);
});
Dá para ver que é fácil não perceber.
Lembre-se: caso essa notificação seja exibida, verifique suas cadeias de promessas e o event.waitUntil()
.
Na próxima seção, vamos analisar o que podemos fazer para estilizar notificações e o conteúdo que podemos exibir.
A seguir
- Visão geral das notificações push na Web
- Como o push funciona
- Assinar um usuário
- UX de permissão
- Como enviar mensagens com bibliotecas push da Web
- Protocolo push da Web
- Como lidar com eventos push
- Como mostrar uma notificação
- Comportamento das notificações
- Padrões de notificação comuns
- Perguntas frequentes sobre notificações push
- Problemas comuns e como informar bugs