问题
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