WordPress中Service Worker推送重复通知问题求助
Hey there, let's tackle this multiple notifications issue you're facing when publishing new posts in WordPress with Service Workers. Let's break down the potential causes and fix them step by step:
1. Fix the Async Logic for Service Worker Unregistration & Registration
Your current code unregisters existing SWs but immediately registers a new one without waiting for the unregistration to complete. Since unregister() is asynchronous, this can leave old SW instances running alongside the new one—resulting in multiple listeners for push messages.
Update your code to wait for all unregistrations to finish before registering the new SW:
if ('serviceWorker' in navigator) { navigator.serviceWorker.getRegistrations().then(async function(registrations) { // Wait for each SW to unregister completely for (let registration of registrations) { await registration.unregister(); } // Now register the new SW var myId = obj.messagingSenderId; const reg = await navigator.serviceWorker.register( `firebase-messaging-sw.js?messagingSenderId=${myId}` ); console.log("SW registration succeeded. Scope is " + reg.scope); messaging.useServiceWorker(reg); await reg.update(); // Request permission only after SW setup is done await requestPermission(); }).catch(function(err) { console.error("SW registration failed with error " + err); }); }
Using async/await ensures each asynchronous step completes before moving on, preventing overlapping SW instances.
2. Avoid Duplicate Firebase Messaging Subscriptions
If your code doesn't check for existing subscriptions, you might end up with multiple valid tokens for the same device. When your backend sends pushes, it will send to every token—causing duplicate notifications.
Modify your requestPermission function to check for an existing token first:
async function requestPermission() { const permission = await Notification.requestPermission(); if (permission === 'granted') { const currentToken = await messaging.getToken(); if (currentToken) { // Send existing token to your WordPress backend (no need to re-subscribe) sendTokenToServer(currentToken); } else { // Only subscribe if no valid token exists const token = await messaging.getToken({ vapidKey: 'YOUR_VAPID_KEY' }); sendTokenToServer(token); } } }
Also, add deduplication logic in your WordPress backend: store only the latest token per user/device, and delete old tokens to avoid redundant pushes.
3. Check for Duplicate Triggering in WordPress Backend
Sometimes the issue isn't frontend-related—your WordPress hook for sending pushes might be firing multiple times (e.g., the publish_post hook can trigger more than once in some scenarios).
Add a transient lock to your backend push code to ensure a single post only triggers one push:
add_action('publish_post', 'send_new_post_notification', 10, 2); function send_new_post_notification($post_id, $post) { // Prevent duplicate pushes for the same post within 5 minutes if (get_transient('post_notified_' . $post_id)) { return; } // Your push notification logic here (send to subscribed users) // Set a transient to mark the post as notified set_transient('post_notified_' . $post_id, true, 5 * MINUTE_IN_SECONDS); }
4. Ensure Single Push Listener in Service Worker
Double-check your firebase-messaging-sw.js to make sure you're only registering one push event listener. Multiple listeners will each fire a notification when a push arrives:
// Correct: Register only one push listener self.addEventListener('push', function(event) { const payload = event.data?.json() || {}; const title = payload.notification.title || 'New Post Alert'; const options = { body: payload.notification.body, icon: payload.notification.icon }; event.waitUntil( self.registration.showNotification(title, options) ); });
Walk through these fixes, and you should stop seeing duplicate notifications when publishing new posts!
内容的提问来源于stack exchange,提问作者raju_odi

