Chrome: Serviceworker Won't Transition To Running State When Receiving Push Message

222 views Asked by At

We have implemented an SDK to ease the process of sending and receiving Push Notification. However, recently we are facing an issue that results in receiving Generic Notification(i.e., This site has been updated in the background) message whenever we send a push message.

After a period of inspection and trial-and-error, we came to the rough conclusion that:

  • Whenever we send a Push Notification, the first time around, service worker won't wake up and hang in the Stopped state. As a result,Generic Notification is shown. In immediate subsequent Push Messages, service worker transitions to Running state and receives Push Messages.
  • The following code responsible for handling push event is not invoked the first time sending Push Message.
@serviceWorkerEvent('push')
    public static async onPushEvent(context: Context, event: PushEvent) {
        context.api.pushDelivered({
            // Sending Analytics
        }).catch(e => log.error('e'));

        const notificationOptions: NotificationOptions = {
            // Notification Options
        };

        const notifTitle = notificationData.title || '';
        await (await context.serviceWorker.registration).showNotification(notifTitle, notificationOptions);

        await context.workerMessenger.broadcast(WORKER_MESSAGE_TYPES.PUSH_RECEIVED, notificationData);
    }

P.S. Using a wrapper function containing event.waitUntil(), we are awaiting for the promises inside to resolve.

1

There are 1 answers

1
jackdbd On

This is the intended behavior. Your service worker is not handling the first push event because your page is still an uncontrolled client for it. Your service worker is not yet in the active state.

From The Service Worker Lifecycle (a highly recommended read):

A service worker won't receive events like fetch and push until it successfully finishes installing and becomes "active".

To handle the first push event you can either:

  1. call location.reload() in your service worker registration script
  2. call clients.claim() in your service worker

Option 2 overrides the default behavior of the service worker and let it take control of uncontrolled clients (your sw immediately claims the clients).

See also: