Remove a Web Push Notification

跟風遠走 提交于 2021-02-07 17:53:10

问题


Is there a way to remove a Web Push Notification once shown? To remove it from the notification list on the device - or mark it as "read"?

I assume this can't be done from the server, and I've been hunting around for a Javascript API - but I haven't found anything.

(The wider problem that I'm trying to crack is how to synchronise notifications on multiple screens/browsers/devices.)


回答1:


I think might be impossible. As you can show and hide a notification. And this can be a workaround for default browser action as described here

Chrome will only show the "This site has been updated in the background." notification when a push message is received and the push event in the service worker does not show a notification after the promise passed to event.waitUntil() has finished.




回答2:


The closes solution that I found was closing the notification after it was shown. Below is the code solution that I have.

event.waitUntil(
    self.registration.showNotification(title, options)
    .then(function (data) {
        self.registration.getNotifications()
        .then(function (notifications) {
            setTimeout(function () {
                //console.log(notifications);
                notifications.forEach(notification => notification.close())
            }, 10);
        })
    })
);



回答3:


Even though it's not possble to revoke push messages, it is possible to close one, using:

// app.js
navigator.serviceWorker.ready.then(reg => {
  reg.getNotifications().then(notifications => {
    for (let i = 0; i < notifications.length; i += 1) {
      notifications[i].close();
    }
  });
});

You could even send a new WebPush message from the back-end with a special action in the payload, for example data: { action: 'close', id: 123 } to trigger messages to be closed. The 'push' eventListener can relay a 'message' event to all clients to close the given (or all) open notifications.

// sw.js
self.addEventListener('push', event => {
  let opts = event.data.json();

  if (opts.data && opts.data.action) {
    event.waitUntil(clients.matchAll().then(windowClients => {
      for (let i = 0; i < windowClients.length; i += 1) {
        windowsClients[i].postMessage(opts.data);
      }
    });
  }
});

// app.js
navigator.serviceWorker.addEventListener('message', event => {
  if (event.data && event.data.action && event.data.action === 'close') {
    closeNotification(event.data.id);
  }
});

function closeNotification(id) {
  navigator.serviceWorker.ready.then(reg => {
    reg.getNotifications().then(n => {
      for (let i = 0; i < n.length; i += 1) {
        if (n[i].data && n[i].data.id && n[i].data.id === id) {
          n[i].close();
        }
      }
    });
  });
}

The biggest downside is that this method only works for active / open clients. I haven't found a way around that.

Used sources:

  • https://developer.mozilla.org/en-US/docs/Web/API/Client/postMessage
  • https://web-push-book.gauntface.com/common-notification-patterns/#merging-notifications
  • https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration/getNotifications


来源:https://stackoverflow.com/questions/49488408/remove-a-web-push-notification

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!