Usando la API de Notificaciones
La API de Notificaciones permite a una página web enviar notificaciones que se mostrarán fuera de la web al nivel del sistema. Esto permite a las aplicaciones web enviar información al usuario aunque estas estén de fondo.
Nota:
Esta característica está disponible en Web Workers.Para comenzar, tenemos que saber qué son las notificaciones y cómo se muestran. En la imagen de abajo se puede ver un ejemplo de notificaciones en android.
El sistema de notificaciones variará según el navegador y la plataforma en la que estemos, pero esto no va a suponer ningún problema. La API de notificaciones está escrita de manera que sea compatible con la gran mayoría de sistemas.
Ejemplos
Un ejemplo claro de uso de notificaciones web puede ser un mail basado en web o una aplicación IRC que nos notificará cada vez que nos llegue un nuevo mensaje, aunque estemos fuera de la aplicación. Un ejemplo de esto lo podemos ver en Slack.
Hemos escrito un par de ejemplos del mundo real para dar una idea más clara de cómo podemos usar las notificaciones web:
- Lista de pendientes: Esto es una app sencilla que almacena las tareas pendientes localmente usando IndexedDB y avisa al usuario cuándo hay que realizar las tareas mediante notificaciones. Descarga el código, o echa un vistazo al ejemplo en tiempo real.
- Emogotchi: Una parodia absurda de Tamagotchi, en la que tienes que mantener a tu Emo miserable o perderás el juego. Esto usa las notificaciones del sistema para indicarte cómo lo estás haciendo y para quejarse de ti, TODO EL RATO. Descarga el código de Emogotchi, o echa un vistazo a la versión en tiempo real.
.
Pidiendo permiso
Antes de que una app pueda lanzar una notificación, el usuario tiene que darle permiso para ello. Esto es un requisito común cuando una API intenta interactuar con algo fuera de una página web — al menos una vez, el usuario tendrá que permitir a la aplicación mostrar notificaciones, de esta forma, el usuario decide qué aplicaciones le pueden mostrar notificaciones y cuáles no.
Comprobando el permiso actual
Puedes comprobar si ya tienes permiso comprobando la propiedad Notification.permission
de solo lectura. Esta puede tener uno de los siguientes valores:
default
- No se le ha pedido permiso al usuario aún, por lo que la app no tiene permisos.
granted
- El usuario ha permitido las notificaciones de la app.
denied
- El usuario ha denegado las notificaciones de la app.
Obteniendo permiso
Si la aplicación aún no tiene permiso para mostrar notificaciones, tendremos que hacer uso de Notification.requestPermission()
para pedir permiso al usuario. En su manera más simple, tal y como se usa en la Demo de Emogotchi (código fuente), solo tenemos que incluir lo siguiente:
Notification.requestPermission().then(function(result) {
console.log(result);
});
Esto usa la versión promise del método, que está soportada en las versiones recientes (p.ej. Firefox 47). Si quieres soportar versiones más antiguas tendrás que usar la versión de callback, que es la siguiente:
Notification.requestPermission();
La versión de callback acepta de forma opcional una función callback que será ejecutada cuando el usuario responda a si quiere notificaciones o no (tal y como se ve en el segundo else ... if
abajo). Por lo general, pedirás permiso para mostrar notificaciones una vez que hayas inicializado la app, y antes de lanzar una notificación. Si quieres ser muy cuidadoso puedes usar lo siguiente (ver To-do List Notifications):
function notifyMe() {
// Comprobamos si el navegador soporta las notificaciones
if (!("Notification" in window)) {
alert("Este navegador no soporta las notificaciones del sistema");
}
// Comprobamos si ya nos habían dado permiso
else if (Notification.permission === "granted") {
// Si esta correcto lanzamos la notificación
var notification = new Notification("Holiwis :D");
}
// Si no, tendremos que pedir permiso al usuario
else if (Notification.permission !== 'denied') {
Notification.requestPermission(function (permission) {
// Si el usuario acepta, lanzamos la notificación
if (permission === "granted") {
var notification = new Notification("Gracias majo!");
}
});
}
// Finalmente, si el usuario te ha denegado el permiso y
// quieres ser respetuoso no hay necesidad molestar más.
}
Nota: Antes de la versión 37, Chrome no te deja llamar a Notification.requestPermission()
en manejador de eventos load
(ver problema 274284).
Permisos en Firefox OS manifest
Ten en cuenta que mientras la API de Notificaciones no esté privileged o certified, deberías seguir inculyendo una entrada en tu archivo manifest.webapp
cuando vayas a usarlo en una app en Firefox OS:
"permissions": { "desktop-notification": { "description": "Needed for creating system notifications." } }, "messages": [{"notification": "path/to/your/index.html"}]
Nota: Cuándo una aplicación es instalada, no deberías de necesitar explicitly request permission, pero vas a seguir necesitando los permisos y las entradas de texto de arriba para poder lanzar las notificaciones.
Creando una notificación
Crear una notificación es fácil, simplemente usa el constructor Notification
. Este constructor espera un título que mostrar en la notificación y otras opciones para mejorar la notificación, como un icon
o un texto body
.
Por ejemplo, en el Ejemplo de Emogotchi tenemos dos funciones que pueden ser llamadas cuando hay que lanzar una notificación; el uso de una u otra depende de si queremos establecer el contenido de la notificación, o si queremos una notificación con contenido aleatorio:
function spawnNotification(theBody,theIcon,theTitle) {
var options = {
body: theBody,
icon: theIcon
}
var n = new Notification(theTitle,options);
setTimeout(n.close.bind(n), 5000);
}
function randomNotification() {
var randomQuote = quoteChooser();
var options = {
body: randomQuote,
icon: 'img/sad_head.png',
}
var n = new Notification('Emogotchi says',options);
setTimeout(n.close.bind(n), 5000);
}
Cerrando las notificaciones
Firefox y Safari cierran las notificaciones automáticamente tras cierto tiempo (unos 4 segundos). Esto también puede suceder a nivel de sistema operativo (en Windows duran 7 segundos por defecto). En cambio, en algunos navegadores no se cierran automáticamente, como en Chrome, por ejemplo. Para asegurarnos de que las notificaciones se cierran en todos los navegadores, al final de las funciones de arriba, llamamos a la función {domxref("Notification.close")}} dentro de setTimeout()
para cerrar la notificación tras 5 segundos. Date cuenta también del uso que hacemos de bind()
para asegurarnos de que la función close()
está asociada a la notificación.
setTimeout(n.close.bind(n), 5000);
Nota: Cuándo recibes un evento "close", no hay ninguna garantía de que haya sido el usuario quién ha cerrado la notificación. Esto coincide con la especificación que dice: "Cuando una notificación es cerrada, sea por la misma plataforma o por el usuario, se deben lanzar los pasos de cierre para la misma".
Eventos de Notificación
Las especificaciones de la API de notificaciones listan cuatro eventos que pueden ser lanzados en la instancia Notification
:
click
- Lanzado cuando el usuario hace click en la notificación.
error (en-US)
- Lanzado cuando algo falla en la notificación; habitualmente es porque la notificación no se ha podido mostrar por algún motivo.
Estos eventos se pueden monitorizar usando los manejadores onclick
y onerror
(en-US). Como Notification
también hereda de EventTarget
, es posible usar el método addEventListener()
en ella.
También hay otros dos eventos que estaban listados en la especificación, pero que han sido eliminados recientemente. Estos puede que sigan funcionando en los navegadores por ahora, pero deberían tratarse como obsoletos y evitar su uso:
close
- Lanzado cuándo la notificación se cierra.
show (en-US)
- Lanzado cuándo la notificación se muestra al usuario.
Reemplazando notificaciones existentes
Normalmente los usuario no quieren recibir muchas notificaciones en poco tiempo — por ejemplo, una aplicación de mensajería que te notifica cada mensaje que te llegue, y te llegan un montón. Para evitar el spam de notificaciones, se puede modificar la cola de notificaciones, reemplazando una o varias notificaciones pendientes, por una nueva notificación.
Para hacer esto, se puede añadir una etiqueta a cualquier nueva notificación. Si ya hay una notificación con la misma etiqueta y aún no se ha mostrado, la nueva reemplazará a la anterior. Si la notificación con la misma etiqueta ya ha sido mostrada, se cerrará la anterior y se mostrará la nueva.
Ejemplo de etiquta
Teniendo el siguiente código HTML:
<button>Notifícame!</button>
Es posible controlar múltiples notificaciones de la siguiente forma:
window.addEventListener('load', function () {
// Primero, comprobamos si tenemos permiso para lanzar notificaciones
// Si no lo tenemos, lo pedimos
if (window.Notification && Notification.permission !== "granted") {
Notification.requestPermission(function (status) {
if (Notification.permission !== status) {
Notification.permission = status;
}
});
}
var button = document.getElementsByTagName('button')[0];
button.addEventListener('click', function () {
// Si el usuario ha dado permiso
// le intentamos enviar 10 notificaciones
if (window.Notification && Notification.permission === "granted") {
var i = 0;
// Usamos un inteval porque algunos navegadores (Firefox incluído) bloquean las notificaciones si se envían demasiadas en cierto tiempo.
var interval = window.setInterval(function () {
// Gracias a la etiqueta, deberíamos de ver sólo la notificación "Holiws! 9"
var n = new Notification("Holiwis! " + i, {tag: 'soManyNotification'});
if (i++ == 9) {
window.clearInterval(interval);
}
}, 200);
}
// Si el usuario no ha dicho si quiere notificaciones
// Nota: en Chrome no estamos seguros de si la propiedad permission
// esta asignada, por lo que es inseguro comprobar el valor "default".
else if (window.Notification && Notification.permission !== "denied") {
Notification.requestPermission(function (status) {
// Si el usuario acepta
if (status === "granted") {
var i = 0;
// Usamos un inteval porque algunos navegadores (Firefox incluído) bloquean las notificaciones si se envían demasiadas en cierto tiempo.
var interval = window.setInterval(function () {
// Gracias a la etiqueta, deberíamos de ver sólo la notificación "Holiws! 9" var n = new Notification("Holiwis! " + i, {tag: 'soManyNotification'});
if (i++ == 9) {
window.clearInterval(interval);
}
}, 200);
}
// Otherwise, we can fallback to a regular modal alert
else {
alert("Hi!");
}
});
}
// If the user refuses to get notified
else {
// We can fallback to a regular modal alert
alert("Hi!");
}
});
});
Comprueba el ejemplo en directo abajo:
Receiving notification of clicks on app notifications
When a user clicks on a notification generated by an app, you will be notified of this event in two different ways, depending on the circumstance:
- A click event if your app has not closed or been put in the background between the time you create the notification and the time the user clicks on it.
- A system message otherwise.
See this code snippet for an example of how to deal with this.
Especificaciones
Especificación | Estado | Comentario |
---|---|---|
Notifications API | Living Standard | Living standard |
Compatibilidad de navegadores
BCD tables only load in the browser