Web Notification API

Trabalha com desenvolvimento web há mais de 12 anos, atuando com projetos open source, palestrante, instrutor, e sócio fundador da Nasc, além de ser curador e idealizador da ​BrazilJS. Também um GDE.

A API de notificações já está bastante madura e funcional. Basicamente, o que a API de notificações faz é solicitar permissão ao usuário para que uma determinada página possa exibir uma mensagem, mesmo que o usuário não esteja mais com o foco nesta página, ou esteja até mesmo fora do browser.

Para explicar como isto funciona, nada melhor que um demo! Abra este live demo sobre Web Notification API que fiz, justamente para vermos um passo-a-passo. O código fonte está disponível no github.

Permissions

Uma das vantagens desta API é que podemos saber exatamente o status da permissão que o usuário nos deu.

Para isto, criei uma função chamada getStatus.

function getStatus () {
    if (!window.Notification) {
        return "unsupported";
    }
    return window.Notification.permission;
}

Sendo que window.Notification.permission pode ser:

  • default: Suportado, mas nunca solicitado ao usuário.
  • denied: Solicitado, e negado pelo usuário.
  • granted: Solicitado, e liberado pelo usuário.

Quando perguntado, o usuário pode liberar as notificações, pode bloquea-las, ou pode simplesmente clicar no “x”, deixando o status atual (por padrão, default).

Solicitando permissão

Antes de criarmos qualquer notificação, é preciso solicitarmos a permissão para o usuário.

Isto não pode acontecer de forma programática, ou seja, é preciso que o pedido tenha partido de uma interação do usuário, como um click em algo. Desta forma, fica claro para o usuário que é ele quem está, explicitamente, interagindo com esta solicitação. A mesma regra é válida para outras APIs, como ao solicitar o uso da câmera ou microfone.

Para solicitarmos a permissão, utilizamos o método requestPermission, do objeto global Notification. Este método recebe uma função, que será disparada quando o usuário finalizar sua interação, recebendo o status final da mesma. retorna uma promise. O uso de callbacks por parâmetro foi depreciado.

Notification.requestPermission().then(status => {
    if (status == 'granted') {
        console.log('permissão concedida');
    }else{
        // pode ser default, ou denied
        console.log(status);
    }
});

A solicitação de permissão será algo parecido com isto: Solicitação de permissão para Web Notification

O que fiz aqui, foi criar uma Promise que resolverá quando o usuário clicar permitir, e será rejeitada quando as notificações forem bloqueadas ou ignoradas. Além disto, chamo uma função (updateStatus) que simplesmente mostra no DOM, para o usuário, o status atual. Desta forma, podemos fazer um tratamento para quando as permissões são liberadas ou não. Poderia por exemplo, fazer algum tratamento de log ou no dom, sempre que as permissões forem solicitadas. Você poderia usar diretamente o método requestPermission.then, caso não queira fazer nenhum tratamento extra.

function getPermission () {
    return new Promise((resolve, reject) => {
        Notification.requestPermission().then(status => {
            updateStatus(status);
            if (status == 'granted') {
                resolve();
            }else{
                reject(status);
            }
        });
    });
}

Desta forma, poderemos tanto solicitar a permissão, quanto também usar a promise em todas as vezes que dispararmos uma notificação. Isto deve garantir que nossa notificação funcione. Ainda ganhamos mais a possibilidade de lidarmos com a situação, caso a notificação não tenha sido disparada por que o usuário a bloqueou. Sinta-se a vontade para exibir a informação de outra forma, como uma modal ou uma mensagem no próprio DOM, por exemplo.

Disparando uma mensagem

Ao disparar uma mensagem sem antes ter solicitado a permissão, a mesma não será disparada…e nenhum erro será anunciado em nosso console!

É aí que nossa Promise fica ainda mais útil.

// Lembre-se, precisamos de uma interação do usuário
// como ponto de partida
document.querySelector('#btn2')
    .addEventListener('click', function () {
        // sempre solicitamos a permissão
        getPermission()
            .then(function(){
                // e quando temos a permissão
                var n = new Notification("Hello!", {
                    // use \n para quebrar linhas
                    body: "Corpo\nda mensagem",
                     // opcional
                    icon: './felipenmoura.jpg'
                });
            }).catch(function(status){
                // permissão negada(ou default)
                console.log('Had no permission!');
                // mostre a mensagem de outra forma
            });
    }
);

Pronto, simples assim, agora nós podemos até mesmo saber quando o usuário simplesmente fechou nosso pedido de permissões.

Caso o usuário não tenha dado permissão, ou não tenha sido perguntado ainda, qualquer notificação disparada programaticamente cairá em nosso catch, permitindo que exibamos a mensagem de outra forma, utilizando o próprio DOM. No catch, podemos também exibir um botão ao usuário, solicitando a permissão a partir do click dele.

Desenvolvendo

Podemos solicitar as permissões todas as vezes, pois o navegador só perguntará uma vez.

Mas quando estamos desenvolvendo, isto pode ser um problema! Para alterarmos manualmente o status de permissão em uma página, clique no ícone no início da url e veja as opções.

No Firefox: Alterando manualmente as permissões para Web Notification no Firefox

No Chrome: Alterando manualmente as permissões para Web Notification no Chrome

Suporte

Uma ampla gama de browsers já oferece suporte às notificações. Mas você pode visualizar uma lista atualizada no caniuse

Concluindo

Espero que tenham gostado e que esta abordagem com Promises facilite a vida de vocês.

Uma lista de outros materiais que valem a pena dar uma olhada:


BrazilJS é uma iniciativa NASC